A running labbook for ideas in the Ahnold project

Bioregions

Looking at @Hamilton2010, bioregions clearly play a role. You could include them simply as covariates. But, that doesn’t account for the potential interactions between MPAs and regions. Might need to either run them as seperate models (worth it to see), with interaction effects with MPA to see if there are differences among bioregions in MPA effects

Interspecies Interactions

Can you look at the spatial-covariance matrix of these species?

Or is there enough data to sugihara the damn thing, and ask whether some species seem to cause decreases in others?

Landings data

Can be found here Can pretty easily figure out a way to scrape all this

Fixed effects, random effects, and errors in variables, and clustering

It’s important that you get this straightened out.

The “errors in variables” relates to the idea that your covariate data are now random draws from some distribution. So, for example, you observe length data, which you fit to a model that predicts length data and a standard deviation, and you pass those predicted length data to some other part of the model. See box 6.2.2 in bayesian primer. This is just basically saying as another random variable in the liklihood, instead of taking it as given (where you would just use the length data)

Basically, what I’m trying to figure out here is how to properly deal with the the clustering of the data in the time series. So, for any categorical variable that is at a higher level than the data, it seems reasonable to just give it a prior (e.g. all the year coefficients share a common prior), all the species effects share a prior by group, etc, where all of those share a common prior.

What do you do about things like linf though? Repeated a whole ton over time, but you can’t just give it a hierarchical prior…. Looking at Gelman and Hill

OOOOOOOHHHHHH, maybe this is the right approach. Give it species fixed effects, and then make the species fixed effects a regression of species effects coefficients on life history traits. So, a multi-level modeling approach, like Gelman and Hill page 241.

From a hierarchichal perspective then, the idea is now to think of these as a bunch of nested regressions for each level of the data, with the right random effects linking each layer together.

So, you have year terms, and those year terms are a function of yearly things like temperature and el niño, species terms, etc. The problem that you’ve been having, and this probably explains some of the convergance issues, is that you have massive colinearity when you try and include fixed effects for things like species, and then the covariates at the species level? So, this allows you to sort of get the best of both worlds, where you now get the “intercepts” by the right thing, but those intercepts take into account the data at the intercept level that you have that can influence the outcome. So it looks though from Gelman and Hill page 281 that to do this, you don’t have to include those terms in the mixed effects part of the regression itself, but only put them in, but with the appropriate priors. So, that’s where the common prior comes in? You’ll just need to mess with this one with code once you can code it in STAN

You should test this by getting the thing written in STAN, and comparing two versions, one where you do it the usual way (estimate the mean of the prior), one where you include covariates in the model, the other where you fit them seperately

AHA@@!!@!#@!@#! THAT’S WHY THE MEAN OF THE PRIOR IS 0!!!! think about it. Say you want to include fixed effects for each site. Under the model as it get’s written all over the place here, they are distributed with mean(u,sigma). Now, when you include the fixed effects mean in that context: those are deviations from a mean 0! So, you’ve already accounted for the change from the mean effect by including the intercept. If you then say include site specific temperature in there, you’d just chuck it in as a variable, which would do the exact same thing as saying N(site + temp,sigma), or site + temp + n(0,sigma). All those terms are getting soaked up in the intercept. Suppose that it should be N(.2,sigma). So, no matter what, ever year term is going to be .2 +- some term. That is the same then as just adding .2 to the intercept, and then setting the mean of the prior to 0. So, they real key here then is simply specifying the group-level standard deviation. Wow.

Everything is a random effect in bayes, the key is is it grouped

Model Structure

Let’s go through the thing from scratch and think through how you want this thing to look, from a model diagramming perspective.

Hurdle component

Data

So may be you need to be thinking about this kind of like a CPUE standardization, where on one hand you’re fitting a poisson distribution to the transect data, and using that to estimate densities, based on deterministic equations and a sigma (or maybe treating that part as data to make things a bit easier), and then fitting the regression to those densities. The challenging part is how you rationalize the two distributions for density; that implied by the regressin and that implied by the error from the logit model

AHA, so the key here is thinking about the marginal posterior of the regression coefficients, not just the regression coefficients. The sigma of the regression model us saying taking those data as observations from a ranfom event, how well does the model explain that. But, that’s just under that one scenario. So, if you were doing this in a simple way where the posterior is analytical, then you get the betas out. But, the full marginal now would take into account the range of worlds that the densities could live in, so you’d sample from the joint posterior to get the betas of interest!

Process

See box 6.2.2 in a Bayesian Primer for ideas on this.

The way I’m leaning towards is something like this: There is a true biomass that is a random draw from a distribution with mean observed biomass and a variance defined by…. something (observer, group, a function of kelp, vis, etc.). The inverse of that, that the observed are a random draw from some true distribution with mean true and sigma above seems hard to do in this context: you’d have to fit a massive number, or possibly an unidentifiable number, of means, unless you want to say that that there’s some clustering (e.g. mean by species by site by year, which I think are the raw aggregation anyways).

Ah wait, you’re making this wayyyy to complicated. The thing you’re thinking about here are errors in predictor variables, not dependent variables like the density, which is what you’re trying to explain. Under a traditional Bayesian framework, the dependent variabels are already considered random draws (until they are obsered), while the rest are considered data. But, the stuff you were thinking of there are for independent variables, things like temperature. So, you could say that temperature is imperfectyl measured, and comes from a distribution with some true mean and sigma.

So, you don’t need to mess with the “errors” in density, since it’s already considered a random draw, from a distribution with mean expeced density from the model itself, and a sigma estiamted by the model.

Now, where things could then get interesting is using a model to estimate the sigmas. i.e. sigma is a linear function of say a constant, plus kelp cover + vis + research group… etc.

Now, that’s all assuming that the biomass densities are in fact your data. There’s another way you could do this, somewhat similar to @Karnauskas2011. The idea here. you have twoish data sources. One are the actual lengths. The other are the observed densities. The goal is still to fit a regression to the densities. The issue now though is that you’re going to fit the regression to densities estimated from the raw length data. So, you’d take the length data. You’d then use that length data to build up a model of densities that you then fit the regression on. The problem is, you’d need a model relating something back to the length data, which you aren’t really doing here. i.e what would the lengths be conditional on? Alternatively, you treat the lengths as data, and the densities as random variables. Now, you have the observed densities, that are draws from a distribution with mean of predicted density, where predicted density is a function of the lengths? That is a bit of double dipping though. Now one option could be to train the regression on “density” data generated from the lengths. So now, you say the observed densities are drawn from a distribution predicted by the regression, where the regression is trained on the expected densities predicted from the length data, estimating sigmas all the way. This seems maybe the most robust option, but also a royal pain in the ass. And do you really gain a whole lot from that?

It seems like you have something like three different model structures all models can share a common hierarchical nature to the data, the question really is how do you want to model errors, especially conditional on what you really care about are doing a good job on the estimators, not on the out-of-sample prediction

  1. The standard model, with potential for clustering of errors in densities as a function of appropriate levels (e.g. species groups, etc. ).That’s really what equation 6.2.51 in BP is doing: making a more complex model of the error structure associated with the observations.

  2. A model for standard deviations in the densities, where sigma is a linear function of an intercept and apprpriate covariates (like visibility, kelp, etc.) Could be an interesting way to test things that need to be accounted for in the model. That’s really what equation 6.2.51 in BP is doing: making a more complex model of the error structure associated with the observations.

  3. A data-generation model, where the length frequency are taken as perfectly observed, or are used to generate draws from a poisson, a la @Karnauskas2011, converted to densities, and then the regression is fit to those densities, and then used to predict the observed densities. Seems like a worse and worse idea, especially if you’re not as interested in prediction as you are in estimation.

Parameters

Let’s think about the covariates first. The question is basically how do you want to cluster the errors. #### Sites

You have site specific parameters, like location, region, etc. These stay constant at each site over time. Those should almost certainly be modeled as random effects, where maybe each site gets an intercept, drawn from the region that it’s in, and each region then get’s an uninformative prior, since the region’s aren’t really random effects, but constant enities in this world.

Now one question I have then is how does that fit in a regression framework, i.e. relative to “controlling” for the region effect in the regression itself. I don’t think that it matters, you just need to stop thinking abotu things so linearly. You’re only goal is to model the variation in density as a function of things, and this goes in there, the effect of region just isn’t a linear additive term, but rather affects the site specific terms

Species

You also have a bunch of species-specific effects. Now, on one level, these make more sense to me as fixed effects (the idea is that they aren’t really random draws from a population, but rather “true” values). But, where I get confused then is how to deal with these correctly in a panel framework, given that they are repeated. If I remember my Gelman, the way to deal with this in the year terms for example is by giving them a hierarchichal nature.

So, maybe one way to think of all the life history things is that each life history value is a draw from a “random” model that genrates life history traits. So, you estimate the coefficients for linf, where linf is a random variable drawn a global distribution.

AHA, i think your confusion is in differentiating the data from the coefficients. I think the “random effects” vs “fixed effects” question relates to how you want to model the data itself, as either the data, or draws from some distribution that you then estimate as well.

“In Bayesian hierarchical modeling, random effects are used to describe variation that occurs beyond variation that arises from sampling alone”

Hobbs, N. Thompson; Hooten, Mevin B.. Bayesian Models: A Statistical Primer for Ecologists (Page 114). Princeton University Press. Kindle Edition.

Priors

Jan 3 2017

New thoughts on model structure

OK, after doing some reading I think I’m geting a better handle on this. The key question: how do you properly account for the sampling nature of the MLPA data

The problem is you’ve been thinking about this rather confusedly between the unclear distinction between hierarchical and state space (see your evernore entry on state space modeling).

So let’s start from the ground up.

  1. You observe samples of length data, binned by size
  2. These sample arrise from a underlying true length structure, let’s say a Poisson, meaning that the mean and SD are the same. So, you fit a model that replicates this process WRONG!!!
    • The samples are the data! they are the mean values of the true poisson distribution. So, if that’s the case, none of this matters ha, since there’s nothing to estimate.

If that’s the case, maybe you go back to an explicit observation model, where the error in the length structures/biomass are a function of covariates.

library(tidyverse)
huh <- rpois(1000,100)
data_frame(huh = huh) %>% 
  ggplot(aes(huh)) + 
  geom_bar()

rmultinom(10, size = 12, prob = c(0.1,0.2,0.8,.1))
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    1    0    1    0    0    1    2    2    0     2
[2,]    2    0    3    4    3    3    0    0    2     1
[3,]    7    9    8    6    9    8    7   10    9     8
[4,]    2    3    0    2    0    0    3    0    1     1

1/4/17

OK, that was a good road to head down, but not a great place to start. It seems like there’s not really a huge upside to be had from the crazy length-up modeling process. At the end of the day, unless you introduce a bias term or something like that, you’re just going to get the mean of the prediction back. So, you could certainly introduce a bit more uncertainty, but not really a substantive change in the outcome.

library(tidyverse)
dat <- read_csv('../data/UCSB_FISH raw thru 2013.csv')
Parsed with column specification:
cols(
  .default = col_character(),
  year = col_integer(),
  month = col_integer(),
  day = col_integer(),
  transect = col_integer(),
  count = col_integer(),
  fish_tl = col_double(),
  min_tl = col_integer(),
  max_tl = col_integer(),
  depth = col_double(),
  vis = col_double(),
  temp = col_double(),
  pctcnpy = col_integer()
)
See spec(...) for full column specifications.
dat <-  dat %>% 
  mutate(size_range = ifelse(is.na(max_tl - min_tl), 0, max_tl - min_tl ))
dat %>% 
  ggplot(aes(size_range)) +
  geom_histogram() + 
  scale_y_log10()

Almost all the observations have no real range to them. Looking at a histogram of the range of the sizes reported (max - min), where 0 corresponds to no range reported, almost all are within a few centimeters, which really isn’t going to play our in the biomass all that much. only NaN% of samples have size ranges above 10 centimeters. So, to be really really precise, you could simulate length frequences for those, but really hardly seems worth the effort.

The bigger question then is if you want to try and model bias in the observations; e.g. counts of certain species really should be higher/lower under different conditions. Something like a “standardized” survey index. i.e. maybe counts should be higher, taking into account poor vis or the like. Basically, it will be important if it introduces bias, or there is substantially more error around particular kinds of species. But beyond that, not like your analysis is fundamentally flawed or anything, and it’s unclear how much benefit you get from controlling for those factors at the ground level, vs. controlling for them in the regression itself (i.e. all else being equal visibility drives down/up counts).

There’s still the biomass issue (converting lengths into biomass). There’s obviously error in there, but probably not bias, so again, the issue would really be in just adding more noise. It’s hard to know how you’d deal with that since there’s not really a signal in the data to tell you anything about that error. It would be nice to work with Jen to do the translation from lengths to densities right there in the model, but again that seems like a second order thing: I don’t think the existing densities are wrong or anything. The biggest thing though is that doing the densities raw would allow you to actually tally them up at the aggregation level you want, instead of taking means/medians across space and time, which could disguise some trends. Let’s work on that actually.

So, I think you’re back go the important thing being doing a good job of dealing with the hierarchical nature of the data themselves. So let’s spend the next few days focusing on that.

Data Exploration

Let’s go back to square one and think a little about the nature of the data that you’re dealing with, and explore the relationships of the data with density and length.

length_data <- read_csv('../data/UCSB_FISH raw thru 2013.csv') %>% 
    magrittr::set_colnames(.,tolower(colnames(.)))
Parsed with column specification:
cols(
  .default = col_character(),
  year = col_integer(),
  month = col_integer(),
  day = col_integer(),
  transect = col_integer(),
  count = col_integer(),
  fish_tl = col_double(),
  min_tl = col_integer(),
  max_tl = col_integer(),
  depth = col_double(),
  vis = col_double(),
  temp = col_double(),
  pctcnpy = col_integer()
)
See spec(...) for full column specifications.
conditions_data <- length_data %>% 
  group_by(site,side,year) %>% 
  summarise(mean_temp = mean(temp, na.rm = T),
            mean_kelp = mean(pctcnpy, na.rm = T),
            mean_vis = mean(vis, na.rm = T)) 
  
life_history_data <- read_csv('../data/VRG Fish Life History in MPA_04_08_11_12 11-Mar-2014.csv') %>%
  rename(classcode = pisco_classcode) %>% 
  magrittr::set_colnames(.,tolower(colnames(.)))
Parsed with column specification:
cols(
  .default = col_character(),
  include = col_integer(),
  Juv.cut.cm = col_double(),
  WL_a = col_double(),
  WL_b = col_double(),
  LC.a._for_WL = col_double(),
  LC.b._for_WL = col_double(),
  VBGF.Linf = col_double(),
  VBGF.k = col_double(),
  VBGF.t0 = col_double(),
  VBGF.Linf.F = col_double(),
  VBGF.k.F = col_double(),
  VBGF.t0.F = col_double(),
  VBGF.Linf.M = col_double(),
  VBGF.k.M = col_double(),
  VBGF.t0.M = col_double(),
  LC.a._for_VBGF = col_double(),
  LC.b._for_VBGF = col_double(),
  F_a = col_double(),
  F_b = col_double(),
  Size_Mature_cm = col_double()
  # ... with 7 more columns
)
See spec(...) for full column specifications.
site_data <- read_csv('../data/Final_Site_Table_UCSB.csv') %>%
    magrittr::set_colnames(.,tolower(colnames(.)))
Parsed with column specification:
cols(
  SITE = col_character(),
  SIDE = col_character(),
  SITE_SIDE = col_character(),
  MPAGROUP = col_character(),
  MPA_STATUS = col_character(),
  RESERVE = col_character(),
  USE = col_character(),
  REGION = col_character(),
  YEAR_MPA = col_integer(),
  MPAAREANM2 = col_double(),
  MPASHORENM = col_double(),
  lat_wgs84 = col_double(),
  lon_wgs84 = col_double()
)
length_data <- length_data %>% 
  left_join(life_history_data, by = 'classcode') %>% 
  left_join(site_data, by = c('site','side'))

Converting length to biomass/density

One thing I’d like to be able to do is move directly from the lengths to the density at any aggregation that I’m interested in by actually tallying the length structure. As it stands right now, you need to take means/medians to aggregate densities over time, which I don’t really like

Let’s take a look at the actual density data that Jen provides

density_data <- read_csv('../data/ci_reserve_data_final3 txt.csv') %>%
  magrittr::set_colnames(.,tolower(colnames(.))) %>% 
  gather('concat.name','value', grep('_',colnames(.)),convert = T) %>%
  mutate(data.type = gsub('\\_.*', '', concat.name),
         classcode = gsub('.*\\_','',concat.name)) %>%
  mutate(value = as.numeric(value)) %>%
  spread(data.type,value) %>%
  rename(site_side = site.side)
Parsed with column specification:
cols(
  .default = col_double(),
  site = col_character(),
  side = col_character(),
  year = col_integer(),
  fishtrans = col_integer(),
  fish_BATH = col_integer(),
  fish_AINE = col_integer(),
  fish_CFAL = col_integer(),
  fish_CPUG = col_integer(),
  fish_NUNI = col_integer(),
  fish_ACAL = col_integer(),
  fish_HAZU = col_integer(),
  fish_SDAL = col_integer(),
  fish_SUMB = col_integer(),
  fish_PHOL = col_integer(),
  fish_RPRO = col_integer(),
  fish_XCAL = col_integer(),
  fish_RALL = col_integer(),
  fish_NCEP = col_integer(),
  fish_BOTH = col_integer(),
  fish_AVUL = col_integer()
  # ... with 59 more columns
)
See spec(...) for full column specifications.
density_example <- density_data %>% 
  filter(is.na(biomass) == F & biomass >0) %>% 
  sample_n(1)
density_example

Let’s take a look and see if you can replicate this density example.

length_to_weight <-
  function(mean_length,
  min_length,
  max_length,
  count,
  weight_a,
  weight_b,
  length_units = 'cm',
  weight_units = 'g',
  length_for_weight_units = 'mm',
  length_type_for_weight,
  tl_sl_a,
  tl_sl_b,
  tl_sl_type,
  tl_sl_formula) {
  #
  # generate_lengths <- function(count,mean_length, min_length, max_length){
  
  if (is.na(count) | count == 0){
    
    outweight <-  0
  }  else {
    
  if (is.na(min_length) |
  is.na(max_length)) {
  #generate distribution of lengths
  
  lengths <-  rep(mean_length, count)
  
  } else{
  # lengths <-  pmax(min_length,pmin(max_length,rpois(count, lambda = mean_length)))
  lengths <- runif(count, min = min_length, max = max_length)
  }
  if (length_type_for_weight == 'SL') {
  if (tl_sl_type  == 'TYPICAL') {
  weight_lengths <-  lengths * tl_sl_a + tl_sl_b
  } else{
  weight_lengths <- (lengths - tl_sl_b) / tl_sl_a
  
  }
  
  } else {
  weight_lengths <-  lengths
  }
  
  if (length_units == 'cm' & length_for_weight_units == 'mm') {
  weight_lengths <- weight_lengths * 10
  }
  
  weight <-  weight_a * weight_lengths ^ weight_b
  
  if (weight_units == 'kg') {
  weight <- weight * 1000
  }
  outweight = sum(weight)
  }
    return(outweight)
  } #close function
  
length_example <- length_data %>% 
  filter(classcode == toupper(density_example$classcode)
, site == density_example$site, 
         side == density_example$side, year == density_example$year) 
length_example <-   length_data %>% 
  filter(is.na(commonname) == F) %>% 
  mutate(biomass_g = pmap_dbl(list(mean_length = fish_tl,
                                      min_length = min_tl,
                                      max_length = max_tl,
                                      count = count,
                                      weight_a = wl_a,
                                      weight_b = wl_b,
                                      length_type_for_weight = wl_input_length,
                                      length_for_weight_units = wl_l_units,
                                      tl_sl_a = lc.a._for_wl,
                                      tl_sl_b = lc.b._for_wl,
                                      tl_sl_type = lc_type_for_wl,
                                      tl_sl_formula = ll_equation_for_wl), length_to_weight))
NAs producedNAs producedNAs producedNAs produced
length_example %>% 
  select(biomass_g)
biomass_data <- length_example %>% 
  group_by(classcode, site, side, year, transect) %>% 
  summarise(total_biomass_g = sum(biomass_g)) 

First, need to add back in zeros. You need a function that goes through trip by trip, and adds in zeros for all species seen at that site at some point but not on that trip.

species_sightings <- length_data %>% 
  group_by(site) %>% 
  summarise(species_seen = list(unique(classcode)))
biomass_data <- biomass_data %>% 
  ungroup() %>% 
  select(site,side,year, transect) %>% 
  unique() %>%  {
  pmap(
    list(
      this_site = .$site,
      this_side = .$side,
      this_year = .$year,
      this_transect = .$transect
    ),
    add_missing_fish,
    observations = biomass_data,
    species_sightings = species_sightings
  )
} %>% 
  bind_rows()
man_density_data <- biomass_data %>% 
  group_by(classcode, site, side,year) %>% 
  summarise(mean_biomass_g = mean(total_biomass_g, na.rm = T)) %>% 
  mutate(
            biomass_g_per_m2 = mean_biomass_g / (30*4),
            biomass_g_per_hectare = biomass_g_per_m2 * 10000,
            biomass_ton_per_hectare = biomass_g_per_hectare * 1e-6)

OK! You’ve got hand calculated densities now, let’s compare them to jens

density_comp_plot <- density_data %>% 
  select(classcode, site, side, year, biomass) %>% 
  mutate(classcode = toupper(classcode)) %>% 
  left_join(man_density_data, by = c('classcode','site','side','year')) %>% 
  left_join(life_history_data, by = 'classcode') %>% 
  ggplot(aes(biomass,biomass_ton_per_hectare, color = commonname)) + 
             geom_abline(aes(intercept = 0, slope = 1), linetype= 2) +
           geom_point() + 
  scale_color_discrete(guide = F) + 
  labs( y = 'Biomass (tons per hectare) - calculated from lengths and weights', x = 'Biomass (tons per hectare) - from ci_reserve_data_final3 txt.csv', 
  caption = 'Resolution is at species-year-site-side')
density_comp_plot
ggsave(density_comp_plot, file = 'density comparison plot.pdf',dev = cairo_pdf)
Saving 7.29 x 4.51 in image

# plotly::ggplotly(density_comp_plot)

Not Bad. It’s a good starting point, and makes me confident that I’m understanding things right. You’ll need to talk with Jen to figure out why this isn’t 1:1. This also let’s you compare outcomes under the two sources. ## Exploring relationships

Let’s dig into things a bit here and just look at trends in the (to start with) two versions of the database

man_density_data <- man_density_data %>% 
  left_join(life_history_data, by = 'classcode') %>% 
  left_join(site_data, by = c('site','side'))
man_density_data %>% 
  filter(is.na(targeted) == F) %>% 
  group_by(region, year, targeted) %>% 
  summarise(median_biomass = mean(biomass_ton_per_hectare, na.rm = T)) %>% 
  ggplot(aes(year,median_biomass, color = targeted)) + 
  geom_line() + 
  facet_wrap(~region)

Now same thing, but with Jen’s data

density_data %>% 
  mutate(classcode = toupper(classcode)) %>% 
    left_join(life_history_data, by = 'classcode') %>% 
  filter(is.na(targeted) == F) %>% 
  group_by(region, year, targeted) %>% 
  summarise(mean_biomass = mean(biomass, na.rm = T)) %>% 
  ggplot(aes(year,mean_biomass, color = targeted)) + 
  geom_line() + 
  facet_wrap(~region)

And just a really quick regression exploration

reg_data <- density_data %>% 
  mutate(classcode = toupper(classcode)) %>% 
    left_join(life_history_data, by = 'classcode') %>% 
      left_join(conditions_data, by = c('site','side','year')) %>% 
  filter(is.na(targeted) == F) %>% 
  filter(biomass > 0) %>% 
  mutate(log_biomass = log(biomass),
         mlpa_in_effect = as.numeric(year > 2003),
         fished = as.numeric(targeted == 'Targeted'),
         did = as.numeric(fished * year * mlpa_in_effect))
reg_fmla <- as.formula('log_biomass ~  as.factor(year) + fished +  as.factor(did) + trophicgroup + vbgf.linf +
                       mean_temp')
basic_reg <- lm(reg_fmla, data = reg_data)
# stan_reg <- rstanarm::stan_glm(reg_fmla, data = reg_data)
summary(basic_reg)

Call:
lm(formula = reg_fmla, data = reg_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-8.6300 -1.0031  0.1861  1.2185  7.4898 

Coefficients:
                                        Estimate Std. Error t value Pr(>|t|)    
(Intercept)                           -4.7443927  0.3248828 -14.603  < 2e-16 ***
as.factor(year)2000                   -0.3839197  0.2902987  -1.322 0.186035    
as.factor(year)2001                   -0.7474464  0.3002206  -2.490 0.012804 *  
as.factor(year)2002                   -0.9318372  0.2784394  -3.347 0.000821 ***
as.factor(year)2003                   -1.2505112  0.2634377  -4.747 2.10e-06 ***
as.factor(year)2004                   -1.5210538  0.2644595  -5.752 9.13e-09 ***
as.factor(year)2005                   -1.3494622  0.2568724  -5.253 1.53e-07 ***
as.factor(year)2006                   -1.4227991  0.2570623  -5.535 3.20e-08 ***
as.factor(year)2007                   -1.4540782  0.2571524  -5.655 1.61e-08 ***
as.factor(year)2008                   -2.1078080  0.2568756  -8.206 2.61e-16 ***
as.factor(year)2009                   -1.2413963  0.2568777  -4.833 1.37e-06 ***
as.factor(year)2010                   -0.9394307  0.2612564  -3.596 0.000325 ***
as.factor(year)2011                   -1.1199622  0.2612836  -4.286 1.83e-05 ***
as.factor(year)2012                   -1.6021303  0.2621615  -6.111 1.03e-09 ***
as.factor(year)2013                   -1.1653702  0.2664487  -4.374 1.24e-05 ***
fished                                 0.9818545  0.1440916   6.814 1.01e-11 ***
as.factor(did)2004                    -0.3440541  0.2259494  -1.523 0.127867    
as.factor(did)2005                    -0.2747237  0.1862225  -1.475 0.140182    
as.factor(did)2006                    -0.2430356  0.1879294  -1.293 0.195965    
as.factor(did)2007                     0.0281801  0.1854401   0.152 0.879219    
as.factor(did)2008                     0.3224524  0.1869612   1.725 0.084615 .  
as.factor(did)2009                     0.0030925  0.1854786   0.017 0.986698    
as.factor(did)2010                    -0.2608361  0.2043295  -1.277 0.201795    
as.factor(did)2011                    -0.0863844  0.2068926  -0.418 0.676299    
as.factor(did)2012                    -0.0125608  0.2085814  -0.060 0.951982    
as.factor(did)2013                    -0.0996501  0.2245465  -0.444 0.657210    
trophicgroupbenthic micro-invertivore -0.8805295  0.0580442 -15.170  < 2e-16 ***
trophicgroupherbivore                  0.8533675  0.0767618  11.117  < 2e-16 ***
trophicgrouppiscivore                 -0.7031733  0.0745551  -9.432  < 2e-16 ***
trophicgroupplanktivore                0.0802367  0.0677855   1.184 0.236569    
vbgf.linf                             -0.0004153  0.0001775  -2.340 0.019321 *  
mean_temp                              0.1349210  0.0120940  11.156  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.748 on 9105 degrees of freedom
  (4753 observations deleted due to missingness)
Multiple R-squared:  0.1602,    Adjusted R-squared:  0.1574 
F-statistic: 56.05 on 31 and 9105 DF,  p-value: < 2.2e-16
broom::tidy(basic_reg)
  basic_reg %>%
    broom::tidy() %>%
    filter(str_detect(term,'did')) %>%
    mutate(year = as.numeric(str_replace(term,'as.factor\\(did\\)','')) )%>%
    ggplot() +
    geom_hline(aes(yintercept = 0)) + 
    geom_pointrange(aes(x = year, y = estimate, ymin = estimate - 1.96*std.error, ymax = estimate + 1.96 * std.error)) +
    geom_smooth(aes(x = year, y = estimate), method = 'lm')

  
    # stan_reg %>%
    # broom::tidy() %>%
    # filter(str_detect(term,'did')) %>%
    # mutate(year = as.numeric(str_replace(term,'as.factor\\(did\\)','')) )%>%
    # ggplot() +
    # geom_pointrange(aes(x = year, y = estimate, ymin = estimate - 1.96*std.error, ymax = estimate + 1.96 * std.error)) + 
    #       geom_smooth(aes(x = year, y = estimate), method = 'lm')
reg_data <- man_density_data %>% 
  ungroup() %>% 
  filter(is.na(targeted) == F) %>% 
  filter(biomass_ton_per_hectare > 0) %>% 
  mutate(log_biomass = log(biomass_ton_per_hectare),
         mlpa_in_effect = as.numeric(year > 2003),
         fished = as.numeric(targeted == 'Targeted'),
         did = as.numeric(fished * year * mlpa_in_effect))
reg_fmla <- as.formula('log_biomass ~  as.factor(year) + fished +  as.factor(did) + trophicgroup + vbgf.linf')
basic_reg <- lm(reg_fmla, data = reg_data)
# stan_reg <- rstanarm::stan_glm(reg_fmla, data = reg_data)
# summary(basic_reg)
# 
# broom::tidy(basic_reg)
  basic_reg %>%
    broom::tidy() %>%
    filter(str_detect(term,'did')) %>%
    mutate(year = as.numeric(str_replace(term,'as.factor\\(did\\)','')) )%>%
    ggplot() +
    geom_hline(aes(yintercept = 0)) + 
    geom_pointrange(aes(x = year, y = estimate, ymin = estimate - 1.96*std.error, ymax = estimate + 1.96 * std.error)) +
    geom_smooth(aes(x = year, y = estimate), method = 'lm')

  
    # stan_reg %>%
    # broom::tidy() %>%
    # filter(str_detect(term,'did')) %>%
    # mutate(year = as.numeric(str_replace(term,'as.factor\\(did\\)','')) )%>%
    # ggplot() +
    # geom_pointrange(aes(x = year, y = estimate, ymin = estimate - 1.96*std.error, ymax = estimate + 1.96 * std.error)) + 
    #       geom_smooth(aes(x = year, y = estimate), method = 'lm')

Well that’s not encouraging: this suggests that the density calculation really does matter here. You’ll go with Jen’s data for now, but big red flag of something that needs fixing here.

Are unfished and fished valid controls?

There are a few ways you could think about testing for this.

  1. Does the MLPA come out as a causal factor on the unfished species?

  2. Do fished speices/unfished species cause each other (do lags of fished species predict unfished and vice versa)

reg_data <- density_data %>% 
  mutate(classcode = toupper(classcode)) %>% 
    left_join(life_history_data, by = 'classcode') %>% 
  left_join(conditions_data, by = c('site','side','year')) %>% 
  filter(is.na(targeted) == F) %>% 
  filter(biomass > 0) %>% 
  mutate(log_biomass = log(biomass),
         mlpa_in_effect = as.numeric(year > 2003),
         unfished = as.numeric(targeted != 'Targeted'),
         did = as.numeric(unfished * year * mlpa_in_effect))
reg_fmla <- as.formula('log_biomass ~  as.factor(year) + mean_temp+unfished +  as.factor(did) + trophicgroup + vbgf.linf')
basic_reg <- lm(reg_fmla, data = reg_data)
# stan_reg <- rstanarm::stan_glm(reg_fmla, data = reg_data)
summary(basic_reg)

Call:
lm(formula = reg_fmla, data = reg_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-8.6300 -1.0031  0.1861  1.2185  7.4898 

Coefficients:
                                        Estimate Std. Error t value Pr(>|t|)    
(Intercept)                           -3.7625382  0.3408704 -11.038  < 2e-16 ***
as.factor(year)2000                   -0.3839197  0.2902987  -1.322 0.186035    
as.factor(year)2001                   -0.7474464  0.3002206  -2.490 0.012804 *  
as.factor(year)2002                   -0.9318372  0.2784394  -3.347 0.000821 ***
as.factor(year)2003                   -1.2505112  0.2634377  -4.747 2.10e-06 ***
as.factor(year)2004                   -1.8651079  0.3117720  -5.982 2.28e-09 ***
as.factor(year)2005                   -1.6241858  0.2917863  -5.566 2.68e-08 ***
as.factor(year)2006                   -1.6658346  0.2919373  -5.706 1.19e-08 ***
as.factor(year)2007                   -1.4258980  0.2913804  -4.894 1.01e-06 ***
as.factor(year)2008                   -1.7853556  0.2914174  -6.126 9.36e-10 ***
as.factor(year)2009                   -1.2383039  0.2905469  -4.262 2.05e-05 ***
as.factor(year)2010                   -1.2002668  0.3007640  -3.991 6.64e-05 ***
as.factor(year)2011                   -1.2063466  0.3012316  -4.005 6.26e-05 ***
as.factor(year)2012                   -1.6146911  0.3024039  -5.340 9.54e-08 ***
as.factor(year)2013                   -1.2650203  0.3093716  -4.089 4.37e-05 ***
mean_temp                              0.1349210  0.0120940  11.156  < 2e-16 ***
unfished                              -0.9818545  0.1440916  -6.814 1.01e-11 ***
as.factor(did)2004                     0.3440541  0.2259494   1.523 0.127867    
as.factor(did)2005                     0.2747237  0.1862225   1.475 0.140182    
as.factor(did)2006                     0.2430356  0.1879294   1.293 0.195965    
as.factor(did)2007                    -0.0281801  0.1854401  -0.152 0.879219    
as.factor(did)2008                    -0.3224524  0.1869612  -1.725 0.084615 .  
as.factor(did)2009                    -0.0030925  0.1854786  -0.017 0.986698    
as.factor(did)2010                     0.2608361  0.2043295   1.277 0.201795    
as.factor(did)2011                     0.0863844  0.2068926   0.418 0.676299    
as.factor(did)2012                     0.0125608  0.2085814   0.060 0.951982    
as.factor(did)2013                     0.0996501  0.2245465   0.444 0.657210    
trophicgroupbenthic micro-invertivore -0.8805295  0.0580442 -15.170  < 2e-16 ***
trophicgroupherbivore                  0.8533675  0.0767618  11.117  < 2e-16 ***
trophicgrouppiscivore                 -0.7031733  0.0745551  -9.432  < 2e-16 ***
trophicgroupplanktivore                0.0802367  0.0677855   1.184 0.236569    
vbgf.linf                             -0.0004153  0.0001775  -2.340 0.019321 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.748 on 9105 degrees of freedom
  (4753 observations deleted due to missingness)
Multiple R-squared:  0.1602,    Adjusted R-squared:  0.1574 
F-statistic: 56.05 on 31 and 9105 DF,  p-value: < 2.2e-16
broom::tidy(basic_reg)
  basic_reg %>%
    broom::tidy() %>%
    filter(str_detect(term,'did')) %>%
    mutate(year = as.numeric(str_replace(term,'as.factor\\(did\\)','')) )%>%
    ggplot() +
    geom_hline(aes(yintercept = 0)) + 
    geom_pointrange(aes(x = year, y = estimate, ymin = estimate - 1.96*std.error, ymax = estimate + 1.96 * std.error)) +
    geom_smooth(aes(x = year, y = estimate), method = 'lm')

I don’t think that that’s a valid comparison, since you at least assume that the fished aren’t a control. You could also just do a changepoint analysis?

Alternatively, let’s think about this mechanistically. If you believe that the “targeted” classification is real, then by definition the MPA has no direct effect on the fished species. The real question then is whether there are trophic interactions that cause a problem. So, why not run a regression of unfished densities as a function of targeted abundance, controlling for other crap?

Interesting, some evidence of effect but it’s messy, and depends a lot on model specification.

El Niño

a = read_html('https://www.esrl.noaa.gov/psd/enso/mei/table.html') %>% 
  html_node('body') %>% 
  html_text()
enso <- read_lines('https://www.esrl.noaa.gov/psd/enso/mei/table.html')
enso <- enso[str_detect(enso,'\t|(YEAR)')] %>% 
  write('enso.txt')
enso <-  read.csv('enso.txt', sep = '\t', header = F)
table_names <- enso$V1[1] %>% 
  as.character() %>% 
  str_split(boundary('word'), simplify = T) %>% 
  as.character() %>% 
  tolower()
enso <- enso %>% 
  slice(-1) %>% 
  as_data_frame()
colnames(enso) <-  table_names
enso <- enso %>% 
  gather('bimonth','enso',-year)
enso %>% 
  mutate(year = year %>% as.character() %>% as.numeric()) %>% 
  group_by(year) %>% 
  summarise(mean_enso = mean(enso)) %>% 
  ggplot(aes(year, mean_enso)) + 
  geom_point()

 enso <- read_table("http://www.esrl.noaa.gov/psd/gcos_wgsp/Timeseries/Data/nino34.long.anom.data",
            na = c("-99.99", "99.99",'-99'), skip = 1, n_max = lubridate::year(Sys.time()) - 1870 + 1,
            col_names = c("year", 1:12)) %>%
 gather(month, enso, -year) %>%
 mutate(month = as.double(month))
cols(
  year = col_integer(),
  `1` = col_double(),
  `2` = col_double(),
  `3` = col_double(),
  `4` = col_double(),
  `5` = col_double(),
  `6` = col_double(),
  `7` = col_double(),
  `8` = col_double(),
  `9` = col_double(),
  `10` = col_double(),
  `11` = col_double(),
  `12` = col_double()
)

Get PDO

 pdo <- read_table("https://www.esrl.noaa.gov/psd/gcos_wgsp/Timeseries/Data/pdo.long.data",
            na = c("-99.99", "99.99",'-99'), skip = 1, n_max = lubridate::year(Sys.time()) - 1900,
            col_names = c("year", 1:12)) %>%
 gather(month, pdo, -year) %>%
 mutate(month = as.double(month),
        date = lubridate::ymd(paste(year,month,'01', sep = '-')))
cols(
  year = col_integer(),
  `1` = col_double(),
  `2` = col_double(),
  `3` = col_double(),
  `4` = col_double(),
  `5` = col_double(),
  `6` = col_double(),
  `7` = col_double(),
  `8` = col_double(),
  `9` = col_double(),
  `10` = col_double(),
  `11` = col_double(),
  `12` = col_double()
)
pdo %>% 
  filter(year >= 2000) %>% 
  ggplot(aes(date,pdo)) +
  geom_hline(aes(yintercept = 0), linetype = 2) +
  geom_point()

Causal defense ideas

How can you defend the causal nature of the results?

Include a “lead” on the DiD term: This is turned on in the years leading up to the policy, and says that the policy is going to happen. SHould be insignificant if the model is right. Look back at mostly harmless and Olivier’s note

How well does out-of-sample prediction help you with causality? At it’s face it gives evidence that your model is doing a good job of describing the data. But does it imply help with causality? Suppose you had a model that said predict if it’s raining outside based on umbrellas. It’s out of sample prediction would be great, but that doesn’t mean that opening umbrellas is going to cause rain.

Regression Exploration

Goal of this section is to start really digging into the regressions.

Data Exploration

Let’s stick with Jen’s data for now, but cognizant that you need to look into reproducing and sensitivities to transformation assumptions

Pulling in Jen’s density data, merging some useful temperature, site, life history, enso, and PDO data

density_data <- read_csv('../data/ci_reserve_data_final3 txt.csv') %>%
  magrittr::set_colnames(.,tolower(colnames(.))) %>% 
  gather('concat.name','value', grep('_',colnames(.)),convert = T) %>%
  mutate(data.type = gsub('\\_.*', '', concat.name),
         classcode = gsub('.*\\_','',concat.name)) %>%
  mutate(value = as.numeric(value)) %>%
  spread(data.type,value) %>%
  rename(site_side = site.side)
Parsed with column specification:
cols(
  .default = col_double(),
  site = col_character(),
  side = col_character(),
  year = col_integer(),
  fishtrans = col_integer(),
  fish_BATH = col_integer(),
  fish_AINE = col_integer(),
  fish_CFAL = col_integer(),
  fish_CPUG = col_integer(),
  fish_NUNI = col_integer(),
  fish_ACAL = col_integer(),
  fish_HAZU = col_integer(),
  fish_SDAL = col_integer(),
  fish_SUMB = col_integer(),
  fish_PHOL = col_integer(),
  fish_RPRO = col_integer(),
  fish_XCAL = col_integer(),
  fish_RALL = col_integer(),
  fish_NCEP = col_integer(),
  fish_BOTH = col_integer(),
  fish_AVUL = col_integer()
  # ... with 59 more columns
)
See spec(...) for full column specifications.
length_data <- read_csv('../data/UCSB_FISH raw thru 2013.csv') %>% 
    magrittr::set_colnames(.,tolower(colnames(.)))
Parsed with column specification:
cols(
  .default = col_character(),
  year = col_integer(),
  month = col_integer(),
  day = col_integer(),
  transect = col_integer(),
  count = col_integer(),
  fish_tl = col_double(),
  min_tl = col_integer(),
  max_tl = col_integer(),
  depth = col_double(),
  vis = col_double(),
  temp = col_double(),
  pctcnpy = col_integer()
)
See spec(...) for full column specifications.
temperature_data <- length_data %>% 
  group_by(site,side,year) %>% 
  summarise(mean_temp = mean(temp, na.rm = T))
life_history_data <- read_csv('../data/VRG Fish Life History in MPA_04_08_11_12 11-Mar-2014.csv') %>%
  rename(classcode = pisco_classcode) %>%
  mutate(classcode = tolower(classcode)) %>% 
  magrittr::set_colnames(.,tolower(colnames(.)))
Parsed with column specification:
cols(
  .default = col_character(),
  include = col_integer(),
  Juv.cut.cm = col_double(),
  WL_a = col_double(),
  WL_b = col_double(),
  LC.a._for_WL = col_double(),
  LC.b._for_WL = col_double(),
  VBGF.Linf = col_double(),
  VBGF.k = col_double(),
  VBGF.t0 = col_double(),
  VBGF.Linf.F = col_double(),
  VBGF.k.F = col_double(),
  VBGF.t0.F = col_double(),
  VBGF.Linf.M = col_double(),
  VBGF.k.M = col_double(),
  VBGF.t0.M = col_double(),
  LC.a._for_VBGF = col_double(),
  LC.b._for_VBGF = col_double(),
  F_a = col_double(),
  F_b = col_double(),
  Size_Mature_cm = col_double()
  # ... with 7 more columns
)
See spec(...) for full column specifications.
life_names <- c('classcode',colnames(life_history_data)[!colnames(life_history_data) %in% colnames(density_data)])
life_history_data <- life_history_data[ , life_names]
site_data <- read_csv('../data/Final_Site_Table_UCSB.csv') %>%
    magrittr::set_colnames(.,tolower(colnames(.)))
Parsed with column specification:
cols(
  SITE = col_character(),
  SIDE = col_character(),
  SITE_SIDE = col_character(),
  MPAGROUP = col_character(),
  MPA_STATUS = col_character(),
  RESERVE = col_character(),
  USE = col_character(),
  REGION = col_character(),
  YEAR_MPA = col_integer(),
  MPAAREANM2 = col_double(),
  MPASHORENM = col_double(),
  lat_wgs84 = col_double(),
  lon_wgs84 = col_double()
)
site_names <- c('site','side',colnames(site_data)[!colnames(site_data) %in% colnames(density_data)])
site_data <- site_data[,site_names]
enso <- read_csv('../data/enso.csv') %>% 
  group_by(year) %>% 
  summarise(mean_enso = mean(enso, na.rm = T))
Parsed with column specification:
cols(
  year = col_integer(),
  bimonth = col_character(),
  enso = col_double()
)
pdo <- read_csv('../data/pdo.csv') %>% 
group_by(year) %>% 
  summarise(mean_pdo = mean(pdo, na.rm = T))
Parsed with column specification:
cols(
  year = col_integer(),
  month = col_double(),
  pdo = col_double(),
  date = col_date(format = "")
)
comp_data <- density_data %>% 
  left_join(temperature_data, by = c('site','side','year')) %>% 
  left_join(life_history_data, by = 'classcode') %>% 
  left_join(site_data, by = c('site','side')) %>% 
  left_join(enso, by = 'year') %>% 
  left_join(pdo, by = 'year')
  

Data Composition

Let’s look at the distribution of sample size over time; where are your data coming from?

comp_data %>% 
  group_by(year) %>% 
  summarise(num_obs = length(biomass)) %>% 
  ggplot(aes(year, num_obs)) + 
  geom_point()

NA
comp_data %>% 
  group_by(year,targeted) %>% 
  summarise(num_obs = length(biomass)) %>% 
  ggplot(aes(year, num_obs, fill = targeted)) + 
  geom_bar(stat = 'identity')

Huh, so a bunch of the observations are “unknown” on targeting status. Let’s look into this. Beyond that though, the targeted and non-targeted are fairly well balanced.

huh <- comp_data %>% 
  filter(is.na(targeted))
sort(unique(huh$classcode))
  [1] "aarg"           "agafim"         "agua"           "aine"          
  [5] "alamar"         "antsol"         "antspp"         "antxan"        
  [9] "aplcal"         "astarm"         "astser"         "astspp"        
 [13] "avul"           "balnub"         "bfreyoy"        "both"          
 [17] "canspp"         "carnivore"      "cencor"         "cfal"          
 [21] "clup"           "coscos"         "coveraglstr"    "coveranem"     
 [25] "coverbarnac"    "coverbarroc"    "coverbarsan"    "coverbrown"    
 [29] "coverbryo"      "coverclam"      "coverclavspp"   "covercomtun"   
 [33] "covercorcal"    "covercrucor"    "covercucspp"    "covercupcor"   
 [37] "covercysosm"    "coverdeadhold"  "coverdesspp"    "coverdiacal"   
 [41] "coverdicspp"    "coverdiocha"    "coverdodfew"    "coveregrmen"   
 [45] "coverencred"    "covererecor"    "coverfleshy"    "covergorgad"   
 [49] "covergreen"     "coverhetpac"    "coverhydroid"   "coverlamhold"  
 [53] "covermacpyr"    "covermud"       "covermussel"    "coverpacrub"   
 [57] "coverphrcal"    "coverphyspp"    "coversaltri"    "coversarfil"   
 [61] "coversarmut"    "coversarspp"    "coverscallop"   "coverscum"     
 [65] "coverserpet"    "covershell"     "coversoltun"    "coversponge"   
 [69] "coverstycal"    "coverstypor"    "covertubemat"   "covertubeworm" 
 [73] "coverturf"      "cpug"           "cpunyoy"        "cragig"        
 [77] "crysit"         "cryste"         "cucspp"         "cypspa"        
 [81] "cysosmad"       "derimb"         "diccal"         "egrmen"        
 [85] "eisarbad"       "eugrub"         "gorgad"         "halass"        
 [89] "halcor"         "halcra"         "halful"         "halkam"        
 [93] "halruf"         "halspp"         "halwal"         "henlev"        
 [97] "herbivore"      "hlag"           "hsemyoy"        "kelkel"        
[101] "laminaria"      "lepchi"         "lincol"         "loxgra"        
[105] "loxscy"         "luifol"         "lytanaad"       "macpyrad"      
[109] "macstipes"      "medaeq"         "megcre"         "meggib"        
[113] "megspp"         "megund"         "metspp"         "mimfol"        
[117] "mmol"           "murcal"         "murfru"         "ncep"          
[121] "nerlue"         "nontargeted"    "nuni"           "ocalyoy"       
[125] "ortkoe"         "pacfim"         "panint"         "parcal"        
[129] "parpar"         "parspp"         "patmin"         "patr"          
[133] "pclayoy"        "pgla"           "pisbre"         "piscivore"     
[137] "pisgig"         "pisoch"         "planktivore"    "pleu"          
[141] "pmac"           "pnot"           "ptecalad"       "pugpro"        
[145] "pugric"         "pugspp"         "pychel"         "rath"          
[149] "reliefflatrel"  "reliefhirel"    "reliefmodrel"   "reliefsltrel"  
[153] "rjor"           "rpro"           "ryoy"           "saca"          
[157] "smysyoy"        "sneb"           "spauyoy"        "spinyoy"       
[161] "spulyoy"        "ssem"           "strfraad"       "strpurad"      
[165] "styfor"         "stymon"         "substratebedrk" "substratebould"
[169] "substratecob"   "substratesand"  "sumb"           "targeted"      
[173] "tealof"         "tetaur"         "unid"           "urtcol"        
[177] "urticina"       "zexa"          

Aha, these appear to be a a bunch of misc. critters and classification for understory cover. Aslo “young of the year”. Probably best to filter these guys out.

comp_data %>% 
  filter(is.na(commonname) == F) %>% 
   group_by(year) %>% 
  summarise(num_obs = length(biomass)) %>% 
  ggplot(aes(year, num_obs)) + 
  geom_point()

NA
comp_data %>% 
  filter(is.na(commonname) == F) %>% 
  group_by(year,region) %>% 
  summarise(num_obs = length(biomass)) %>% 
  ggplot(aes(year, num_obs, fill = region)) + 
  geom_bar(stat = 'identity')

Huh, worth noting that a few of the islands only come in after 2003. What is this doing to your effect that you’re basically brining in a bunch of new islands with different effects right after implementation of MPAs in 2003?

comp_data %>% 
  filter(is.na(commonname) == F) %>% 
  group_by(year,broadtrophic) %>% 
  summarise(num_obs = length(biomass)) %>% 
  ggplot(aes(year, num_obs, fill = broadtrophic)) + 
  geom_bar(stat = 'identity')

Effect Exploration

Let’s look at the change in density as a functino of a variety of variables

candidates <- c('biomass','year','site','side','classcode',
                'region','broadtrophic','reserve','campus','mpaareanm2','mean_temp','guild','trophicgroup','targeted',
                'mean_enso','mean_pdo','vbgf.k','vbgf.linf','max_length_fishbase')
reg_data <- comp_data[,candidates] %>% 
  filter(is.na(biomass) == 0, is.na(targeted) == F) %>% 
  mutate(log_density = log(biomass),
         factor_year = as.factor(year),
         targeted = as.numeric(targeted == 'Targeted'),
         post_mlpa = as.numeric(year >= 2003),
         reserve = as.numeric(reserve == 'IN'),
         did = as.factor(targeted * post_mlpa * year)
         )
reg_data %>% 
  group_by(year,targeted) %>% 
  summarise(mean_density = mean(biomass, na.rm = T)) %>% 
  ggplot(aes(year,mean_density, color = factor(targeted))) + 
  geom_line()

reg_data %>% 
  group_by(year,targeted,region) %>% 
  summarise(mean_density = mean(log(biomass + 1e-3), na.rm = T)) %>% 
  ggplot(aes(year,mean_density, color = factor(targeted))) + 
  geom_line() + 
  facet_wrap(~region) + 
  ylab('log mean density')

One troubling pattern, both ANA and SCI show that steep drop in densities from 2000-2003, which might really be skewing the effect of the MPAs (that early negative effect), though on the plus side it’s both targetted and non-targeted

Let’s look at some other factors here

reg_data %>% 
  group_by(broadtrophic) %>% 
  summarise(mean_density = mean(biomass, na.rm = T)) %>% 
  ggplot(aes(broadtrophic,mean_density, fill = broadtrophic)) + 
  geom_bar(stat = 'identity')

No surprises, higher density of herbivores

reg_data %>% 
  group_by(region) %>% 
  ggplot(aes(region,biomass, fill = region)) + 
  geom_boxplot()

reg_data %>% 
  select(biomass,year,mean_temp, mean_pdo, mean_enso) %>% 
  gather(metric,value, contains('mean')) %>% 
  group_by(year,metric) %>% 
  summarise(mean_biomass = log(mean(biomass, na.rm = T)), mean_value = mean(value, na.rm = T)) %>% 
  ggplot(aes(mean_value,mean_biomass, fill = metric)) + 
  geom_abline(aes(intercept = mean(mean_biomass, na.rm = T), slope = 0)) + 
  geom_point(shape = 21) + 
  facet_wrap(~metric, scales = 'free_x')

Interesting, definitely some noise in here, but seems to a a trend towards the “mean” of the environmental covariates. Good evidence for throwing a quadratic in here.

environmental_cor = reg_data %>% 
  filter(is.na(mean_temp) == F) %>% 
  select(mean_temp, mean_enso, mean_pdo, year) %>%
  cor() 
corrplot::corrplot(environmental_cor)

Quite a bit of correlation between some of the environmental variables, but you don’t really care about estimating those precisely so not a huge deal.

But, the year thing could be a bit messy, since you have such poor contrast before and after MPA, so might need to look at mean PDO as a problem variable.

DiD Structure

Now, what should the actual difference in difference look like?

The key thing you need is treatment on the treated, so that’s being a fished species post 2003.

If you include species specific fixed effects, then you don’t have to include the general effect of being a fished species, since those will all come out in the wash (i.e. the fished effect is internalized in the species specific fixed effects, or alternatively, you say that the species level effect is a function of covariates, including being fished)

Similarly with post-mpa. If you don’t include year fixed effects, then you need it. But, if you include year fixed effects, then the “post mpa” effect should be soaked up, and in fact perfectly colinear with, the year fixed effects.

So, now, the real pain in the ass is the year terms. Which I think you figured out!

The question then is how do you control for other things.

You could just include the DiD term

Bare-bones regression

Let’s start with a bare bones regression, using rstanarm, one hierarchichal, one not. You’ll then compare your results to one where you code the likelihood yourself

reg_vars <- c('log_density','factor_year', 'year','targeted', 'did', 'region' ,
'mean_enso','mean_pdo', 'mean_temp','classcode','site','side','post_mlpa','region',
'broadtrophic')

has_all <- function(x) any(is.na(x)) == F

pos_reg_data <- reg_data %>% 
  select(-mean_temp) %>% 
  left_join(conditions_data %>% select(site,side,year, contains('mean')), by = c('site','side','year')) %>% 
  filter(biomass >0, year >=2000) %>% 
  select_(.dots = as.list(reg_vars)) %>% 
  mutate(has_all_vars = apply(.,1,has_all)) %>% 
  filter(has_all_vars == T) %>% 
  map2_df(colnames(.), center_scale, omit_names = c('log_density','year','mean_enso','mean_pdo')) %>%
  mutate(did_dummy = 1 * targeted,
         did_year = paste('did',year, sep = '_')) %>% 
  spread(did_year,did_dummy, fill = 0) %>% 
  mutate(temp2 = mean_temp^2,
         pdo2 = mean_pdo^2,
         enso2 = mean_enso^2,
         site_side = paste(site, side, sep = '_'))

# pos_reg_data$did_2003[pos_reg_data$did_2003 == 1] <-  0.5

pos_reg_data %>% 
  group_by(factor_year,targeted) %>% 
  summarise(mb = mean(log_density, na.rm = T)) %>% 
  ggplot(aes(factor_year, mb, color = factor(targeted))) + 
  geom_point()


did_years <- paste('did',2000:2013, sep = '_')

did_year <- did_years[did_years!='did_2000']


simple_reg <-
as.formula(
paste0(
'log_density ~',
paste(did_year, collapse = '+'),
' + (1|year) + (1 + mean_temp + temp2 |classcode) + mean_enso +  mean_pdo + (1 | site_side) + (1 | site) + (1 | region) + targeted + post_mlpa'
)
)

# + vbgf.linf +
# vbgf.k +
# mean_enso + enso2 + mean_pdo + pdo2 + mean_temp  + temp2')

freq_flat_reg <- lme4::lmer(simple_reg, data = pos_reg_data)

flat_reg <- stan_glmer(simple_reg, data = pos_reg_data,chains = 1)


freq_did_plot <-  freq_flat_reg %>% 
  tidy() %>% 
  mutate(lower = estimate - 1.96 * std.error,
         upper = estimate + 1.96 * std.error) %>% 
  filter(str_detect(term,'did')) %>% 
  mutate(year = str_replace(term, 'did_','') %>% as.numeric()) %>% 
  ggplot() +
geom_hline(aes(yintercept = 0)) + 
  geom_vline(aes(xintercept = 2003), color = 'red', linetype = 2) +
  geom_pointrange(aes(year,estimate, ymax = upper, ymin = lower)) + 
  ylab('Estimated MLPA Effect') + 
  ggrepel::geom_text_repel(data = data_frame(x = 2003, y = 1), aes(x,y, label = 'MLPA Enacted'),nudge_x = 2) + 
  xlab('Year')
         
freq_did_plot

did_plot <- flat_reg %>% 
  as.data.frame() 
  
  did_plot <- did_plot[,str_detect(colnames(did_plot), 'did_')] %>% 
  gather(did,effect) %>% 
  mutate(year = str_replace(did,'did_','') %>% as.numeric()) %>% 
  group_by(year) %>% 
  summarise(mean_effect = mean(effect),
            top = sort(effect)[round(.975 * length(effect))],
            bottom = sort(effect)[round(.025 * length(effect))]) %>% 
  ggplot() + 
  geom_hline(aes(yintercept = 0)) + 
  geom_vline(aes(xintercept = 2003), color = 'red', linetype = 2) +
  geom_pointrange(aes(year,mean_effect, ymax = top, ymin = bottom)) + 
  ylab('Estimated MLPA Effect') + 
  ggrepel::geom_text_repel(data = data_frame(x = 2003, y = 1), aes(x,y, label = 'MLPA Enacted'),nudge_x = 2) + 
  xlab('Year')

did_plot
ggsave('new_mlpa_did.pdf',did_plot)

mtcars %>% 
  map_df(center_scale)

Now let’s try and replicate with a custom STAN function

did_plot <- flat_reg %>% 
  as.data.frame() %>% 
  select(contains('classcode')) %>% 
  gather(classcode,effect) %>% 
  mutate(classcode = str_replace(classcode,'classcode',''))

stan_reg_data <- pos_reg_data %>% 
  mutate(year_marker = 1) %>% 
  mutate(year = paste('year',year, sep = '_')) %>% 
  spread(year,year_marker, fill = 0) %>% 
  mutate(classcode = paste('classcode',classcode, sep = '_'),
         class_marker = 1) %>% 
  spread(classcode,class_marker, fill = 0) %>% 
    mutate(site = paste('site',site, sep = '_'),
         site_marker = 1) %>% 
  spread(site,site_marker, fill = 0) %>% 
  select(log_density, contains('year_'), contains('did_'),
         contains('classcode_'), contains('site_')) %>% 
  mutate(constant = 1)

levels_to_drop <- c(min(pos_reg_data$year),sort(unique(pos_reg_data$classcode))[1],
                    sort(unique(pos_reg_data$site))[1])

stan_reg_data <- stan_reg_data %>% 
  select(-year_2000, -did_2003, -site_ANACAPA_ADMIRALS, -classcode_acor)
                    

y <- as.numeric(stan_reg_data$log_density)

x <- stan_reg_data %>% 
  select(-log_density) %>% 
  as.matrix()


stan_fit <- stan(
  file = '../scripts/ahnold_reg.stan',
  data = list(
    num_pars = dim(x)[2],
    num_obs = length(y),
    y = y,
    x = x
  ),
  chains = 4, 
  warmup = 1000,
  iter = 2000,
  cores = 4, 
  refresh = 100
)

did_terms <- which(str_detect(colnames(x),'did'))

did_plot <- stan_fit %>% 
  as.data.frame() %>% 
  select_(.dots = as.list(did_terms)) %>% 
  gather(did,effect) %>% 
  # mutate(year = str_replace(did,'did_','') %>% as.numeric()) %>% 
  group_by(did) %>% 
  summarise(mean_effect = mean(effect),
            top = sort(effect)[round(.975 * length(effect))],
            bottom = sort(effect)[round(.025 * length(effect))]) %>% 
  ggplot() + 
  geom_hline(aes(yintercept = 0)) + 
  # geom_vline(aes(xintercept = 2003), color = 'red', linetype = 2) +
  geom_pointrange(aes(1:length(mean_effect),mean_effect, ymax = top, ymin = bottom)) + 
  ylab('Estimated MLPA Effect') + 
  # ggrepel::geom_text_repel(data = data_frame(x = 2003, y = 1), aes(x,y, label = 'MLPA Enacted'),nudge_x = 2) + 
  xlab('Year')

OK! Things work. Moving over to run_ahnold for formal construction of this process

Multi-level (hierarchichal) notes

OK, so I think I’m finally starting to get the hang of this. The confusion, from a regression point of view, is how mechanical do you have to be about the “multilevel part”.

Look at Gelman 12.15 and the code there.

Your confusion has been, say you’ve got observations at the transect level, and you want to include species level covariates. In a fixed effects world this wouldn’t work: you can’t estiamtes species level fixed effects, along with things like vbk. that don’t vary within a species. You can either include species fixed effects, or component things that define species.

The way Gelman talks about this in multilevel modeling, is that you can instead model this in a hierarchical manner, where the coefficients of the species fixed effects are a function of things like vbk. This makes sense, but the question is the mechanics of this. My impression was that I would have to do this all manually, i.e. take the betas of the fixed effects, then write up a regression of those betas as a function of vbk etc. Makes sense but a total pain in the ass.

Looking at Gelman page 266 though, it becomes clearer. It seems like mechanically you can do this just by converting the fixed effects to clustered random effects, and then including vbk as just another coefficient.

e.g. lmer(y ~ x + vbk + (1 | species))

Propensity Scores

Add in broad bioregion effect

That could just be recovery inside and not spillover. Do you have to have spillover

They don’t count the

Look at Steve’s BACI response to Ray’s

What happens to the regulaions outside in addition to the reserve. A simple model that looks at what would you expect

Good data for the mainland

Look into literature for priors

I’m going to show that you can disentangle recruitment from lenghts

2017-03-15

Expressing MLPA effect

Might be a good idea to show the significance statistically, but the effect through simulation. Simulate draws from the joint posterior with and without MLPA, show mean densities. Easier to understand, allows you to combine the net effect of hurdle component

2017-03-16

Check in with Jen

  • Check in with the idea of more local indicies of ENSO/PDO

  • No big ENSO event till 2013

  • Might need to explore removing painted greenling since they are bottom dwelling cryptic-ish. Tend to be counted more frequently when there wasn’t much else.

  • Drop santa barbara island entirely (one off sample, 4 years)

  • Let’s think about parsing this by species. Fishing is very different across different species in here, what species are really driving the analysis? Are different species disproportionately driving the results

  • We have before and after data from the overflights, so could at least use that as a prior on the scale of redistribution. SAMSAP might be able to pick up the potential “blue paradox” side of things, as

  • What if this is all just a recruitment signal

  • We could look at the SMURF data to get an idea of the recruitment trends

  • Something weird happened in 2008-2010 across all the CI data

  • PISCO assumes that all species have the same probability of being seen anywhere in all the islands. Might be worth looking into what happens if you zero fill by data-base wide

2017-21-03

Things are looking pretty strong. Basic Model diagnostics look solid for the most part, though the LMER approach is a bit skewed to the right. But no alarm bells. The biggest issue is really low effective samples sizes for several species, as well as collinearity between a few of the model parameters (load up the STAN run and launch shinystan to dig into this a bit).

A few things you can do to try and deal with that. Re-run the model with only let’s say the top 75% percentile by positive occurance species, to make sure that you’re not getting too thrown by a bunch of really rare species. Can also try rerunning without painted greenling, since Jen seems to think those buggers might be a problem. I’m a little hesitant to do too much judgement based pruning of the data. Key things is does it really cause the results to break down.

Jen also raised the issue of the zero filling. You did your zero filling by site. It seems that when Jen was going from raw lengths to densities, she was zero filling by region. So, a garibalidi should be missing from every transect in San Miguel. This seems a litle extreme to me, but you can play with this once you get the ability to move from lenghts to densities. I really want to hone in on any subjective decisions that might be driving the results, and this seems like a potentially big candidate .

Update: removing painted greenling has no real effect on results. Phew.

Running now with only the top 50th percentile of species incorporated in the analysis, seeing what that does.

One thought on the random vs. fixed effects thing: should species really be a random effect? Maybe you should only have varying slopes but not intercepts by species, so have fixed effects by species category, and then temperature and region effects by species.

Wooooo species effects don’t matter either

You should go through and spell out why you think some things are random and some are fixed effects, drawing from the gelman framework, where the nature of the hierarchichal prior is really the defining characteristic

Sketching out Hypothesis Runs

What are the hypothetical states of the MPA world that you want to run over? One option is to specify a handful of boutique model runs: model 1, 2, 3 etc, each designed to evaluate a very specific set of circumstances. The other is to specify a set of key levels, and then monte carlo over combinations of those levers.

Regardless, the key things seem to be

  1. Strength of density dependence
  2. Nature of density dependence
  3. initial b and f
  4. Larval movement
  5. Adult movement
  6. Age at maturity
  7. Fleet reaction
  8. Species composition
  9. Scale of MPA relative to movement

The first 6 are relatively straightforward. Seems possibly easier to monte carlo and then pull out case study scenarios that you are interested in, since speed really isn’t the issue here.

You could also use that to easily create ensembles of species.

So, for a given “run” you’d specify how many species you want to generate, and then project them and aggregate. So, you could specify one species if you want ot make it clear, or an assemblage of many different species.

The risk with this approach is that you might just get a gigantic mess of results. But, you can easily pare this approach down to a concrete set if you want. I think this gets away from “cherry picking” scenarios that fit your story. You can present a giant array in trelliscope of outcomes, and then choose some to present in the paper.

  1. Strength of density dependence
    • this is just steepness
  2. Nature of density dependence
    • You can use the babcock definitions that are already in there
  3. f
    • One option is just to say pick a random F
    • The other option is some kind of effort dynamics model, from open access to one way trip etc.
    • Seems excessive, the key thing is it overfished or not, and is it getting worse or not
    • Pick a random f, run it out
    • Stop the thing at some random point…. problem there is you can’t be in “recovery”
  4. Larval movement
    • harder. Will take some thought to do this one right really. Key thing is do you want to deal with larvae or with recruits really. See how you do it in GASP
  5. Adult movement
    • Easy enough, what proportion of adults move from each cell
  6. Age at maturity
    • simple enough
  7. Fleet reaction
    • Dilute
    • Concentrate
  8. Species composition
  9. Scale of MPA relative to movement
    • Make the MPAs about the pattern of CI

For now, let’s take the life history straight out of the data that are actually used. So, grab the species that make it through the filter and project those. So, each run will take the life history data and run with it with a random assortment of traits.

Let’s focus on keeping it simple stupid. Take the species, project forward with a random F and a random stop point, a steepness drawn from the family distribution for that species, a random density denepence form… let’s spell it out

  1. Draw a species from the database
  2. Fill in missing non-variale life history characteristics (e.g. linf)
  3. Randomly assign characteristics of interest (density dependence form, movement, etc.)
  4. Create completed fish object
  5. Create a fleet object
  6. Fill in the fleet object with things like F, or fleet model dynamics etc.
  7. Pass a completed fish and fleet object to sim_fishery
  8. Store results
  9. Repeat runs a whole bunch of times.
  10. Aggregate as desired

4/13/17

As long as the errors in your dependent variable are mean 0, then there’s no problem. If they are not, or if the errors are a function of your dependent variable, then you do have problem

Look in to stratification from that book of Kyles

Check in with COdy

Make mortality/growth rates a function of biomass

Check on lit on this

Make plot of length on x and year on y, so you get a bunch of stacked shifts in cohorts

Maybe add in a ricker function, though might need to double check on the steepness values. You might be moving things over the to right hand side of

Examine OST catch data

ost_region_catch %>% 
  mutate(pounds = str_replace(pounds,',','') %>% as.numeric(),
         revenue = str_replace_all(revenue,"\\$|,",''),
         price = str_replace(`average price`,'\\$','')) %>% 
  group_by(year,fishery) %>% 
  summarise(catch_lbs = sum(pounds, na.rm = T)) %>% 
  ggplot(aes(year,catch_lbs, color = fishery)) + 
  geom_vline(aes(xintercept = 2003), linetype = 2, color = 'red') +
  geom_line()
NAs introduced by coercionWarning messages:
1: Unknown or uninitialised column: 'V1'. 
2: Unknown or uninitialised column: 'V1'. 

Interesting, stablish throughout the SC region, though that’s a pretty damn big area

ost_port_catch %>% 
  filter(port %in% c("Port Hueneme/Oxnard", "Santa Barbara","Ventura")) %>% 
  mutate(pounds = str_replace(pounds,',','') %>% as.numeric(),
         revenue = str_replace_all(revenue,"\\$|,",''),
         price = str_replace(`average price`,'\\$','')) %>% 
  group_by(year,fishery) %>% 
  summarise(catch_lbs = sum(pounds, na.rm = T)) %>% 
  ggplot(aes(year,catch_lbs, color = fishery)) + 
  geom_vline(aes(xintercept = 2003), linetype = 2, color = 'red') +
  geom_line(show.legend = F) + 
  facet_wrap(~fishery, scales = 'free_y') + 
  theme(axis.text.y =  element_blank(),
        axis.text.x = element_blank())
NAs introduced by coercionWarning messages:
1: Unknown or uninitialised column: 'V1'. 
2: Unknown or uninitialised column: 'V1'. 
3: Unknown or uninitialised column: 'V1'. 
4: Unknown or uninitialised column: 'V1'. 

4/14/17

I’m honestly close to out of ideas. These catch dat are pretty worring to be honest. If you buy these data as being representative of the fished species out in the channel islands, then this suggests a decreasin gcatch trend in nearshore finfish catches, not stable or increasing. That really makes it hard to explain the MPA mediated “decrease” in abundance.

Possible explanations that remain.

  1. Some form of density dependent mortality (or ricker like dynamics)
  • Can model this
  1. Catches at the islands themselves have been stable or gone up
  • Can try and get some more regional data to check on this
  1. Ocam’s razor: There was just a dramatic enough shift in sampling regimes when the MPAs went in place that pre-and-post are just not comparable in any way shape of form

  2. Let’s write up the current results and state of the world this weekend/next week and send that to committee for comments

Scraping CDFW Data

map_df(a, process_cdfw)
Called from: .f(.x[[i]], ...)
debug at #21: x <- map_df(x, ~numfoo)
x <- map_df(x, ~numfoo)
Error: cannot convert object to a data frame
x
View(x)
a
[[1]]
      [,1]                                                     [,2]          [,3]         
 [1,] "alifornia Waters"                                       ""            ""           
 [2,] "Fishes"                                                 ""            ""           
 [3,] "Anchovy, northern............................. "        " 1,135,732 " " 1,425,102 "
 [4,] "Barracuda, California......................... "        " 8 "         " 77 "       
 [5,] "Bass, giant sea................................. "      " 85 "        " 63 "       
 [6,] "Blacksmith......................................... "   " 0 "         " 0 "        
 [7,] "Bonito, Pacific................................... "    " 13,618 "    " 38 "       
 [8,] "Butterfish (Pacific pompano)......... "                 " 3 "         " 0 "        
 [9,] "Cabezon............................................ "   " 728 "       " 1,098 "    
[10,] "Croaker, white................................... "     " 986 "       " 946 "      
[11,] "Eel, California moray......................... "        " 0 "         " 0 "        
[12,] "Fish, unspecified............................... "      " 122 "       " 5 "        
[13,] "Flounder, arrowtooth......................... "         " 0 "         " 0 "        
[14,] "Flounder, starry................................. "     " 5 "         " 0 "        
[15,] "Flounder, unspecified........................ "         " 0 "         " 0 "        
[16,] "Flyingfish........................................... " " 0 "         " 0 "        
[17,] "Greenling, kelp.................................. "     " 0 "         " 0 "        
[18,] "Guitarfish, shovelnose....................... "         " 1,391 "     " 314 "      
[19,] "Halfmoon........................................... "   " 0 "         " 0 "        
[20,] "Halibut, California.............................. "     " 17,401 "    " 15,195 "   
[21,] "Halibut, unspecified........................... "       " 36 "        " 19 "       
[22,] "Jacksmelt.......................................... "   " 0 "         " 0 "        
[23,] "Lingcod............................................. "  " 0 "         " 0 "        
[24,] "Lizardfish, California.......................... "      " 36 "        " 0 "        
[25,] "Louvar............................................... " " 0 "         " 0 "        
[26,] "Mackerel, Pacific............................... "      " 1 "         " 0 "        
[27,] "Mackerel, jack................................... "     " 0 "         " 1 "        
[28,] "Opah................................................. " " 97 "        " 0 "        
[29,] "Opaleye............................................. "  " 0 "         " 0 "        
[30,] "Queenfish.......................................... "   " 0 "         " 0 "        
[31,] "Ray, Pacific electric........................... "      " 0 "         " 96 "       
[32,] "Ray, bat............................................. " " 0 "         " 0 "        
[33,] "Rockfish, Pacific ocean perch........... "              " 0 "         " 0 "        
[34,] "Rockfish, black-and-yellow................ "            " 0 "         " 0 "        
[35,] "Rockfish, black.................................. "     " 0 "         " 0 "        
[36,] "Rockfish, blackgill.............................. "     " 0 "         " 38 "       
[37,] "Rockfish, blue................................... "     " 0 "         " 0 "        
[38,] "Rockfish, bocaccio............................ "        " 51 "        " 0 "        
      [,4]        [,5]        [,6]        [,7]          [,8]        [,9]        [,10]      
 [1,] ""          ""          ""          ""            ""          ""          ""         
 [2,] ""          ""          ""          ""            ""          ""          ""         
 [3,] " 207,906 " " 303,040 " " 714,516 " " 1,041,818 " " 789,275 " " 735,579 " " 401,055 "
 [4,] " 33 "      " 1,736 "   " 2,521 "   " 3,047 "     " 818 "     " 177 "     " 211 "    
 [5,] " 129 "     " 71 "      " 351 "     " 537 "       " 651 "     " 154 "     " 9 "      
 [6,] " 0 "       " 0 "       " 0 "       " 0 "         " 0 "       " 0 "       " 0 "      
 [7,] " 0 "       " 0 "       " 0 "       " 0 "         " 0 "       " 0 "       " 289 "    
 [8,] " 53 "      " 27 "      " 55 "      " 0 "         " 0 "       " 0 "       " 0 "      
 [9,] " 2,616 "   " 2,835 "   " 4,955 "   " 6,001 "     " 3,236 "   " 5,076 "   " 6,675 "  
[10,] " 464 "     " 253 "     " 1,606 "   " 443 "       " 117 "     " 7 "       " 859 "    
[11,] " 0 "       " 0 "       " 0 "       " 0 "         " 0 "       " 0 "       " 0 "      
[12,] " 5 "       " 14 "      " 11 "      " 7 "         " 0 "       " 0 "       " 0 "      
[13,] " 0 "       " 5 "       " 0 "       " 0 "         " 0 "       " 0 "       " 0 "      
[14,] " 0 "       " 0 "       " 0 "       " 0 "         " 0 "       " 0 "       " 0 "      
[15,] " 0 "       " 6 "       " 0 "       " 0 "         " 9 "       " 0 "       " 0 "      
[16,] " 0 "       " 0 "       " 0 "       " 0 "         " 0 "       " 5 "       " 0 "      
[17,] " 0 "       " 0 "       " 4 "       " 0 "         " 0 "       " 1 "       " 11 "     
[18,] " 1,841 "   " 1,726 "   " 445 "     " 135 "       " 285 "     " 92 "      " 719 "    
[19,] " 32 "      " 231 "     " 44 "      " 187 "       " 24 "      " 55 "      " 314 "    
[20,] " 22,806 "  " 20,469 "  " 12,895 "  " 31,321 "    " 35,175 "  " 15,626 "  " 8,565 "  
[21,] " 195 "     " 50 "      " 319 "     " 231 "       " 123 "     " 0 "       " 0 "      
[22,] " 0 "       " 0 "       " 0 "       " 0 "         " 0 "       " 0 "       " 1 "      
[23,] " 84 "      " 0 "       " 488 "     " 237 "       " 203 "     " 17 "      " 18 "     
[24,] " 50 "      " 106 "     " 234 "     " 0 "         " 0 "       " 0 "       " 0 "      
[25,] " 0 "       " 0 "       " 0 "       " 22 "        " 0 "       " 54 "      " 28 "     
[26,] " 10 "      " 7 "       " 0 "       " 283,330 "   " 29 "      " 196,139 " " 27,528 " 
[27,] " 0 "       " 0 "       " 0 "       " 0 "         " 16 "      " 20,007 "  " 22 "     
[28,] " 0 "       " 0 "       " 0 "       " 0 "         " 0 "       " 40 "      " 50 "     
[29,] " 3 "       " 0 "       " 0 "       " 0 "         " 5 "       " 0 "       " 0 "      
[30,] " 0 "       " 0 "       " 2 "       " 0 "         " 0 "       " 0 "       " 0 "      
[31,] " 0 "       " 0 "       " 0 "       " 0 "         " 10 "      " 170 "     " 60 "     
[32,] " 0 "       " 0 "       " 0 "       " 0 "         " 45 "      " 25 "      " 18 "     
[33,] " 0 "       " 0 "       " 0 "       " 63 "        " 0 "       " 0 "       " 0 "      
[34,] " 0 "       " 4 "       " 0 "       " 0 "         " 0 "       " 10 "      " 17 "     
[35,] " 0 "       " 0 "       " 489 "     " 0 "         " 0 "       " 0 "       " 0 "      
[36,] " 2,225 "   " 213 "     " 1,554 "   " 995 "       " 777 "     " 29 "      " 2,482 "  
[37,] " 19 "      " 8 "       " 270 "     " 5 "         " 0 "       " 0 "       " 0 "      
[38,] " 26 "      " 13 "      " 58 "      " 65 "        " 49 "      " 30 "      " 27 "     
      [,11]       [,12]       [,13]      [,14]       
 [1,] ""          ""          ""         ""          
 [2,] ""          ""          ""         ""          
 [3,] " 346,156 " " 647,023 " " 75,357 " " 7,822,559"
 [4,] " 199 "     " 253 "     " 80 "     " 9,159"    
 [5,] " 0 "       " 10 "      " 93 "     " 2,154"    
 [6,] " 0 "       " 0 "       " 17 "     " 17"       
 [7,] " 0 "       " 9 "       " 66,625 " " 80,579"   
 [8,] " 80 "      " 284 "     " 50 "     " 552"      
 [9,] " 4,114 "   " 4,195 "   " 5,377 "  " 46,907"   
[10,] " 7,877 "   " 2,565 "   " 9,801 "  " 25,923"   
[11,] " 0 "       " 13 "      " 90 "     " 103"      
[12,] " 0 "       " 0 "       " 0 "      " 164"      
[13,] " 0 "       " 0 "       " 0 "      " 5"        
[14,] " 0 "       " 0 "       " 0 "      " 5"        
[15,] " 0 "       " 0 "       " 0 "      " 15"       
[16,] " 0 "       " 0 "       " 0 "      " 5"        
[17,] " 4 "       " 0 "       " 2 "      " 23"       
[18,] " 2,430 "   " 619 "     " 308 "    " 10,305"   
[19,] " 11 "      " 9 "       " 39 "     " 945"      
[20,] " 9,349 "   " 10,831 "  " 14,724 " " 214,357"  
[21,] " 0 "       " 0 "       " 0 "      " 974"      
[22,] " 0 "       " 0 "       " 0 "      " 1"        
[23,] " 159 "     " 12 "      " 0 "      " 1,217"    
[24,] " 0 "       " 30 "      " 6 "      " 462"      
[25,] " 179 "     " 15 "      " 0 "      " 297"      
[26,] " 1,187 "   " 0 "       " 0 "      " 508,231"  
[27,] " 4 "       " 0 "       " 0 "      " 20,049"   
[28,] " 2,914 "   " 344 "     " 76 "     " 3,521"    
[29,] " 0 "       " 1 "       " 2 "      " 11"       
[30,] " 0 "       " 0 "       " 0 "      " 2"        
[31,] " 80 "      " 0 "       " 0 "      " 416"      
[32,] " 0 "       " 0 "       " 0 "      " 88"       
[33,] " 0 "       " 0 "       " 0 "      " 63"       
[34,] " 3 "       " 0 "       " 0 "      " 33"       
[35,] " 0 "       " 0 "       " 0 "      " 489"      
[36,] " 2,178 "   " 6,766 "   " 598 "    " 17,855"   
[37,] " 15 "      " 0 "       " 11 "     " 327"      
[38,] " 71 "      " 89 "      " 172 "    " 651"      

[[2]]
      [,1]                                                    [,2]        [,3]        [,4]      
 [1,] "alifornia Waters"                                      ""          ""          ""        
 [2,] "Fishes"                                                ""          ""          ""        
 [3,] "Rockfish, brown................................. "     " 0 "       " 0 "       " 17 "    
 [4,] "Rockfish, canary................................ "     " 0 "       " 0 "       " 7 "     
 [5,] "Rockfish, chilipepper......................... "       " 0 "       " 22 "      " 6 "     
 [6,] "Rockfish, copper............................... "      " 0 "       " 0 "       " 278 "   
 [7,] "Rockfish, cowcod.............................. "       " 0 "       " 0 "       " 0 "     
 [8,] "Rockfish, gopher............................... "      " 0 "       " 28 "      " 271 "   
 [9,] "Rockfish, grass................................. "     " 0 "       " 37 "      " 1,143 " 
[10,] "Rockfish, group bolina....................... "        " 0 "       " 0 "       " 2 "     
[11,] "Rockfish, group canary/vermili.......... "             " 0 "       " 0 "       " 0 "     
[12,] "Rockfish, group gopher..................... "          " 0 "       " 0 "       " 46 "    
[13,] "Rockfish, group nearshore................ "            " 0 "       " 0 "       " 155 "   
[14,] "Rockfish, group red........................... "       " 0 "       " 0 "       " 775 "   
[15,] "Rockfish, group rosefish.................... "         " 0 "       " 0 "       " 0 "     
[16,] "Rockfish, group shelf......................... "       " 0 "       " 0 "       " 87 "    
[17,] "Rockfish, group slope........................ "        " 0 "       " 0 "       " 0 "     
[18,] "Rockfish, group small........................ "        " 0 "       " 0 "       " 0 "     
[19,] "Rockfish, kelp.................................... "   " 0 "       " 0 "       " 63 "    
[20,] "Rockfish, rosethorn........................... "       " 0 "       " 0 "       " 0 "     
[21,] "Rockfish, rosy................................... "    " 0 "       " 0 "       " 0 "     
[22,] "Rockfish, splitnose............................ "      " 11 "      " 4 "       " 159 "   
[23,] "Rockfish, starry................................. "    " 0 "       " 0 "       " 14 "    
[24,] "Rockfish, treefish............................... "    " 0 "       " 0 "       " 123 "   
[25,] "Rockfish, unspecified........................ "        " 47 "      " 139 "     " 1,301 " 
[26,] "Rockfish, vermilion............................ "      " 0 "       " 0 "       " 30 "    
[27,] "Rockfish, widow................................ "      " 0 "       " 0 "       " 1 "     
[28,] "Rockfish, yellowtail............................ "     " 0 "       " 31 "      " 0 "     
[29,] "Sablefish........................................... " " 1,877 "   " 1,096 "   " 2,737 " 
[30,] "Salmon, Chinook............................... "       " 0 "       " 0 "       " 0 "     
[31,] "Salmon.............................................. " " 0 "       " 0 "       " 0 "     
[32,] "Sanddab............................................ "  " 323 "     " 238 "     " 193 "   
[33,] "Sardine, Pacific................................. "    " 361,879 " " 966,738 " " 55,708 "
[34,] "Scorpionfish, California..................... "        " 377 "     " 97 "      " 1,931 " 
[35,] "Seabass, white.................................. "     " 3,628 "   " 2,411 "   " 1,973 " 
[36,] "Shark, Pacific angel.......................... "       " 6,880 "   " 5,894 "   " 3,243 " 
[37,] "Shark, basking.................................. "     " 0 "       " 0 "       " 0 "     
[38,] "Shark, bigeye thresher...................... "         " 0 "       " 0 "       " 0 "     
      [,5]        [,6]        [,7]        [,8]        [,9]          [,10]       [,11]      
 [1,] ""          ""          ""          ""          ""            ""          ""         
 [2,] ""          ""          ""          ""          ""            ""          ""         
 [3,] " 51 "      " 76 "      " 9 "       " 0 "       " 658 "       " 0 "       " 0 "      
 [4,] " 0 "       " 662 "     " 0 "       " 0 "       " 0 "         " 0 "       " 0 "      
 [5,] " 4 "       " 0 "       " 7 "       " 6 "       " 1,423 "     " 0 "       " 0 "      
 [6,] " 33 "      " 709 "     " 1,046 "   " 709 "     " 402 "       " 239 "     " 172 "    
 [7,] " 35 "      " 26 "      " 29 "      " 23 "      " 10 "        " 31 "      " 29 "     
 [8,] " 476 "     " 655 "     " 1,212 "   " 771 "     " 227 "       " 667 "     " 592 "    
 [9,] " 2,045 "   " 2,304 "   " 3,275 "   " 1,998 "   " 5,146 "     " 4,515 "   " 2,189 "  
[10,] " 0 "       " 29 "      " 61 "      " 40 "      " 5 "         " 145 "     " 0 "      
[11,] " 0 "       " 0 "       " 0 "       " 0 "       " 0 "         " 0 "       " 0 "      
[12,] " 19 "      " 73 "      " 103 "     " 153 "     " 203 "       " 113 "     " 0 "      
[13,] " 0 "       " 0 "       " 0 "       " 69 "      " 31 "        " 114 "     " 9 "      
[14,] " 1,148 "   " 879 "     " 1,434 "   " 802 "     " 385 "       " 323 "     " 843 "    
[15,] " 0 "       " 0 "       " 0 "       " 0 "       " 42 "        " 666 "     " 107 "    
[16,] " 0 "       " 28 "      " 66 "      " 152 "     " 156 "       " 139 "     " 0 "      
[17,] " 0 "       " 0 "       " 5 "       " 0 "       " 0 "         " 0 "       " 0 "      
[18,] " 7 "       " 14 "      " 0 "       " 0 "       " 0 "         " 0 "       " 0 "      
[19,] " 61 "      " 42 "      " 0 "       " 3 "       " 0 "         " 4 "       " 2 "      
[20,] " 0 "       " 0 "       " 0 "       " 15 "      " 0 "         " 0 "       " 0 "      
[21,] " 0 "       " 0 "       " 13 "      " 65 "      " 0 "         " 0 "       " 0 "      
[22,] " 120 "     " 30 "      " 39 "      " 207 "     " 69 "        " 211 "     " 37 "     
[23,] " 19 "      " 10 "      " 36 "      " 22 "      " 0 "         " 0 "       " 0 "      
[24,] " 169 "     " 214 "     " 463 "     " 559 "     " 142 "       " 266 "     " 62 "     
[25,] " 1,572 "   " 1,369 "   " 2,284 "   " 1,477 "   " 424 "       " 1,555 "   " 396 "    
[26,] " 27 "      " 28 "      " 85 "      " 58 "      " 0 "         " 319 "     " 172 "    
[27,] " 0 "       " 8 "       " 10 "      " 22 "      " 13 "        " 17 "      " 8 "      
[28,] " 0 "       " 0 "       " 0 "       " 0 "       " 8 "         " 0 "       " 9 "      
[29,] " 4,373 "   " 1,630 "   " 3,253 "   " 3,609 "   " 1,262 "     " 6,749 "   " 4,848 "  
[30,] " 0 "       " 220 "     " 0 "       " 0 "       " 0 "         " 860 "     " 0 "      
[31,] " 0 "       " 120 "     " 0 "       " 0 "       " 0 "         " 0 "       " 0 "      
[32,] " 403 "     " 80 "      " 10 "      " 225 "     " 2 "         " 0 "       " 109 "    
[33,] " 300,734 " " 523,580 " " 685,822 " " 283,577 " " 1,408,037 " " 345,353 " " 579,506 "
[34,] " 498 "     " 730 "     " 94 "      " 282 "     " 778 "       " 287 "     " 1,492 "  
[35,] " 90 "      " 369 "     " 24,713 "  " 21,245 "  " 4,381 "     " 1,194 "   " 4,614 "  
[36,] " 1,786 "   " 1,309 "   " 2,157 "   " 618 "     " 758 "       " 777 "     " 3,431 "  
[37,] " 0 "       " 76 "      " 0 "       " 0 "       " 0 "         " 0 "       " 0 "      
[38,] " 0 "       " 0 "       " 358 "     " 0 "       " 0 "         " 0 "       " 0 "      
      [,12]         [,13]       [,14]       
 [1,] ""            ""          ""          
 [2,] ""            ""          ""          
 [3,] " 0 "         " 0 "       " 811"      
 [4,] " 0 "         " 0 "       " 669"      
 [5,] " 0 "         " 0 "       " 1,468"    
 [6,] " 166 "       " 980 "     " 4,732"    
 [7,] " 4 "         " 5 "       " 191"      
 [8,] " 259 "       " 1,342 "   " 6,498"    
 [9,] " 1,653 "     " 2,494 "   " 26,798"   
[10,] " 123 "       " 176 "     " 581"      
[11,] " 18 "        " 5 "       " 23"       
[12,] " 77 "        " 112 "     " 899"      
[13,] " 0 "         " 0 "       " 378"      
[14,] " 865 "       " 2,529 "   " 9,984"    
[15,] " 0 "         " 0 "       " 815"      
[16,] " 0 "         " 0 "       " 626"      
[17,] " 0 "         " 0 "       " 5"        
[18,] " 0 "         " 0 "       " 21"       
[19,] " 0 "         " 18 "      " 192"      
[20,] " 0 "         " 0 "       " 15"       
[21,] " 0 "         " 0 "       " 78"       
[22,] " 0 "         " 40 "      " 927"      
[23,] " 0 "         " 0 "       " 101"      
[24,] " 22 "        " 104 "     " 2,124"    
[25,] " 987 "       " 1,993 "   " 13,545"   
[26,] " 0 "         " 14 "      " 733"      
[27,] " 0 "         " 8 "       " 87"       
[28,] " 3 "         " 12 "      " 64"       
[29,] " 3,463 "     " 5,494 "   " 40,390"   
[30,] " 0 "         " 0 "       " 1,080"    
[31,] " 0 "         " 0 "       " 120"      
[32,] " 0 "         " 43 "      " 1,625"    
[33,] " 1,065,972 " " 248,851 " " 6,825,757"
[34,] " 2,201 "     " 6,195 "   " 14,962"   
[35,] " 3,420 "     " 1,509 "   " 69,546"   
[36,] " 1,045 "     " 5,244 "   " 33,142"   
[37,] " 0 "         " 0 "       " 76"       
[38,] " 0 "         " 0 "       " 358"      

[[3]]
      [,1]                                                     [,2]       [,3]      [,4]     
 [1,] "alifornia Waters"                                       ""         ""        ""       
 [2,] "Fishes"                                                 ""         ""        ""       
 [3,] "Shark, blue........................................ "   " 0 "      " 0 "     " 0 "    
 [4,] "Shark, brown smoothhound............... "               " 285 "    " 174 "   " 431 "  
 [5,] "Shark, dusky..................................... "     " 0 "      " 0 "     " 371 "  
 [6,] "Shark, gray smoothhound................. "              " 0 "      " 0 "     " 0 "    
 [7,] "Shark, horn....................................... "    " 0 "      " 21 "    " 0 "    
 [8,] "Shark, leopard................................... "     " 324 "    " 512 "   " 574 "  
 [9,] "Shark, pelagic thresher..................... "          " 0 "      " 0 "     " 0 "    
[10,] "Shark, sevengill................................. "     " 4 "      " 0 "     " 7 "    
[11,] "Shark, shortfin mako......................... "         " 174 "    " 20 "    " 15 "   
[12,] "Shark, sixgill...................................... "  " 0 "      " 0 "     " 0 "    
[13,] "Shark, smooth hammerhead............. "                 " 0 "      " 0 "     " 0 "    
[14,] "Shark, soupfin................................... "     " 1,765 "  " 1,890 " " 823 "  
[15,] "Shark, spiny dogfish.......................... "        " 0 "      " 0 "     " 6 "    
[16,] "Shark, thresher.................................. "     " 18,674 " " 2,903 " " 86 "   
[17,] "Shark, unspecified............................. "       " 8 "      " 45 "    " 78 "   
[18,] "Shark, white...................................... "    " 0 "      " 0 "     " 0 "    
[19,] "Sheephead, California....................... "          " 4,326 "  " 1,010 " " 4,750 "
[20,] "Silversides......................................... "  " 0 "      " 0 "     " 0 "    
[21,] "Skate, California................................ "     " 1,779 "  " 0 "     " 0 "    
[22,] "Skate, unspecified............................. "       " 20 "     " 0 "     " 113 "  
[23,] "Smelts, true....................................... "   " 0 "      " 0 "     " 0 "    
[24,] "Sole, Dover....................................... "    " 0 "      " 0 "     " 544 "  
[25,] "Sole, English..................................... "    " 96 "     " 20 "    " 62 "   
[26,] "Sole, fantail....................................... "  " 0 "      " 0 "     " 0 "    
[27,] "Sole, petrale...................................... "   " 6 "      " 369 "   " 82 "   
[28,] "Sole, rex............................................ " " 0 "      " 0 "     " 5 "    
[29,] "Sole, unspecified............................... "      " 372 "    " 620 "   " 1,206 "
[30,] "Surfperch, black................................ "      " 0 "      " 0 "     " 0 "    
[31,] "Surfperch, rainbow............................ "        " 4 "      " 0 "     " 0 "    
[32,] "Surfperch, rubberlip........................... "       " 0 "      " 2 "     " 0 "    
[33,] "Surfperch, unspecified....................... "         " 2 "      " 5 "     " 44 "   
[34,] "Swordfish.......................................... "   " 2,126 "  " 0 "     " 0 "    
[35,] "Thornyhead, longspine...................... "           " 1,823 "  " 479 "   " 1,666 "
[36,] "Thornyhead, shortspine..................... "           " 3,811 "  " 2,807 " " 6,480 "
[37,] "Thornyheads..................................... "      " 1,520 "  " 250 "   " 1,096 "
[38,] "Tomcod, Pacific................................ "       " 0 "      " 0 "     " 0 "    
      [,5]      [,6]      [,7]      [,8]      [,9]      [,10]     [,11]     [,12]      [,13]    
 [1,] ""        ""        ""        ""        ""        ""        ""        ""         ""       
 [2,] ""        ""        ""        ""        ""        ""        ""        ""         ""       
 [3,] " 73 "    " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "      " 0 "    
 [4,] " 111 "   " 107 "   " 151 "   " 51 "    " 31 "    " 95 "    " 131 "   " 1,273 "  " 472 "  
 [5,] " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "      " 0 "    
 [6,] " 0 "     " 0 "     " 0 "     " 3 "     " 7 "     " 0 "     " 41 "    " 0 "      " 0 "    
 [7,] " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "      " 0 "    
 [8,] " 701 "   " 893 "   " 520 "   " 674 "   " 219 "   " 130 "   " 194 "   " 259 "    " 191 "  
 [9,] " 0 "     " 18 "    " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "      " 0 "    
[10,] " 0 "     " 7 "     " 0 "     " 0 "     " 10 "    " 0 "     " 0 "     " 0 "      " 0 "    
[11,] " 182 "   " 0 "     " 621 "   " 1,552 " " 82 "    " 1,116 " " 2,080 " " 1,312 "  " 193 "  
[12,] " 0 "     " 0 "     " 0 "     " 15 "    " 0 "     " 0 "     " 0 "     " 0 "      " 0 "    
[13,] " 0 "     " 0 "     " 50 "    " 0 "     " 0 "     " 0 "     " 0 "     " 0 "      " 0 "    
[14,] " 1,427 " " 631 "   " 3,236 " " 4,795 " " 3,847 " " 997 "   " 149 "   " 677 "    " 1,401 "
[15,] " 21 "    " 47 "    " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "      " 0 "    
[16,] " 393 "   " 2,692 " " 5,839 " " 4,706 " " 4,829 " " 6,813 " " 3,770 " " 21,337 " " 3,282 "
[17,] " 18 "    " 0 "     " 7 "     " 0 "     " 0 "     " 0 "     " 6 "     " 46 "     " 55 "   
[18,] " 0 "     " 0 "     " 88 "    " 61 "    " 0 "     " 0 "     " 0 "     " 0 "      " 0 "    
[19,] " 5,775 " " 3,357 " " 7,696 " " 7,458 " " 5,503 " " 9,308 " " 4,274 " " 2,036 "  " 3,144 "
[20,] " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 5 "     " 0 "     " 0 "      " 0 "    
[21,] " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "      " 0 "    
[22,] " 698 "   " 95 "    " 0 "     " 3 "     " 385 "   " 234 "   " 0 "     " 146 "    " 175 "  
[23,] " 0 "     " 0 "     " 9 "     " 0 "     " 2 "     " 0 "     " 0 "     " 0 "      " 0 "    
[24,] " 97 "    " 130 "   " 12 "    " 0 "     " 0 "     " 0 "     " 0 "     " 0 "      " 0 "    
[25,] " 167 "   " 116 "   " 0 "     " 0 "     " 4,732 " " 0 "     " 0 "     " 112 "    " 244 "  
[26,] " 65 "    " 164 "   " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "      " 0 "    
[27,] " 259 "   " 76 "    " 30 "    " 0 "     " 3,686 " " 0 "     " 0 "     " 434 "    " 509 "  
[28,] " 0 "     " 0 "     " 8 "     " 0 "     " 0 "     " 2 "     " 120 "   " 0 "      " 0 "    
[29,] " 1,610 " " 809 "   " 292 "   " 366 "   " 444 "   " 836 "   " 2,988 " " 2,467 "  " 2,097 "
[30,] " 173 "   " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "      " 0 "    
[31,] " 1 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "      " 0 "    
[32,] " 1 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "      " 0 "    
[33,] " 44 "    " 0 "     " 5 "     " 0 "     " 5 "     " 0 "     " 0 "     " 0 "      " 0 "    
[34,] " 0 "     " 0 "     " 0 "     " 0 "     " 10 "    " 350 "   " 3,815 " " 11,157 " " 441 "  
[35,] " 3,566 " " 5,115 " " 4,317 " " 5,987 " " 1,598 " " 2,301 " " 2,600 " " 716 "    " 4,284 "
[36,] " 2,111 " " 6,945 " " 4,202 " " 6,217 " " 1,352 " " 699 "   " 420 "   " 17 "     " 1,414 "
[37,] " 2,278 " " 839 "   " 608 "   " 1,896 " " 669 "   " 266 "   " 2,115 " " 837 "    " 2,657 "
[38,] " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 0 "     " 41 "    " 0 "      " 0 "    
      [,14]    
 [1,] ""       
 [2,] ""       
 [3,] " 73"    
 [4,] " 3,311" 
 [5,] " 371"   
 [6,] " 51"    
 [7,] " 21"    
 [8,] " 5,189" 
 [9,] " 18"    
[10,] " 28"    
[11,] " 7,346" 
[12,] " 15"    
[13,] " 50"    
[14,] " 21,639"
[15,] " 74"    
[16,] " 75,324"
[17,] " 263"   
[18,] " 149"   
[19,] " 58,636"
[20,] " 5"     
[21,] " 1,779" 
[22,] " 1,868" 
[23,] " 11"    
[24,] " 783"   
[25,] " 5,549" 
[26,] " 229"   
[27,] " 5,452" 
[28,] " 135"   
[29,] " 14,106"
[30,] " 173"   
[31,] " 5"     
[32,] " 3"     
[33,] " 105"   
[34,] " 17,898"
[35,] " 34,452"
[36,] " 36,475"
[37,] " 15,030"
[38,] " 41"    

[[4]]
      [,1]                                                     [,2]           [,3]          
 [1,] "alifornia Waters"                                       ""             ""            
 [2,] "Fishes"                                                 ""             ""            
 [3,] "Tuna, albacore.................................. "      " 240 "        " 0 "         
 [4,] "Tuna, bluefin..................................... "    " 0 "          " 0 "         
 [5,] "Tuna, skipjack, black......................... "        " 0 "          " 0 "         
 [6,] "Tuna, skipjack................................... "     " 0 "          " 0 "         
 [7,] "Tuna, unspecified.............................. "       " 12 "         " 0 "         
 [8,] "Tuna, yellowfin.................................. "     " 0 "          " 0 "         
 [9,] "Whitefish, ocean................................ "      " 869 "        " 81 "        
[10,] "Whiting, Pacific................................. "     " 5 "          " 0 "         
[11,] "Yellowtail........................................... " " 203 "        " 34 "        
[12,] "Crustaceans"                                            ""             ""            
[13,] "Crab, box.......................................... "   " 0 "          " 19 "        
[14,] "Crab, claws....................................... "    " 62 "         " 20 "        
[15,] "Crab, king.......................................... "  " 0 "          " 0 "         
[16,] "Crab, pelagic red............................... "      " 0 "          " 0 "         
[17,] "Crab, red rock................................... "     " 0 "          " 0 "         
[18,] "Crab, rock unspecified....................... "         " 38,916 "     " 41,080 "    
[19,] "Crab, spider....................................... "   " 2,443 "      " 2,349 "     
[20,] "Crab, yellow rock............................... "      " 27 "         " 0 "         
[21,] "Crustacean, unspecified.................... "           " 0 "          " 0 "         
[22,] "Lobster, California spiny.................... "         " 28,391 "     " 25,224 "    
[23,] "Prawn, ridgeback.............................. "        " 250,974 "    " 130,744 "   
[24,] "Prawn, spot....................................... "    " 1,475 "      " 18,966 "    
[25,] "Shrimp, mantis.................................. "      " 0 "          " 0 "         
[26,] "Shrimp, ocean (pink).................... "              " 0 "          " 0 "         
[27,] "Echinoderms"                                            ""             ""            
[28,] "Sea cucumber, unspecified............... "              " 5,641 "      " 6,434 "     
[29,] "Sea urchin, purple............................. "       " 0 "          " 141 "       
[30,] "Sea urchin, red.................................. "     " 739,888 "    " 194,690 "   
[31,] "Mollusks"                                               ""             ""            
[32,] "Clam, unspecified.............................. "       " 0 "          " 0 "         
[33,] "Limpet, unspecified........................... "        " 0 "          " 0 "         
[34,] "Mussel.............................................. "  " 20 "         " 250 "       
[35,] "Octopus, unspecified......................... "         " 113 "        " 76 "        
[36,] "Snail, sea.......................................... "  " 38 "         " 0 "         
[37,] "Snails, moon..................................... "     " 0 "          " 0 "         
[38,] "Squid, jumbo..................................... "     " 3 "          " 0 "         
[39,] "Squid, market.................................... "     " 25,142,717 " " 14,809,871 "
      [,4]          [,5]          [,6]          [,7]          [,8]          [,9]       
 [1,] ""            ""            ""            ""            ""            ""         
 [2,] ""            ""            ""            ""            ""            ""         
 [3,] " 0 "         " 0 "         " 0 "         " 0 "         " 157 "       " 0 "      
 [4,] " 0 "         " 0 "         " 0 "         " 0 "         " 0 "         " 0 "      
 [5,] " 0 "         " 0 "         " 0 "         " 0 "         " 0 "         " 0 "      
 [6,] " 0 "         " 0 "         " 0 "         " 0 "         " 0 "         " 0 "      
 [7,] " 0 "         " 0 "         " 0 "         " 0 "         " 0 "         " 0 "      
 [8,] " 0 "         " 0 "         " 0 "         " 16 "        " 218 "       " 0 "      
 [9,] " 886 "       " 778 "       " 363 "       " 591 "       " 608 "       " 390 "    
[10,] " 20 "        " 0 "         " 0 "         " 36 "        " 0 "         " 0 "      
[11,] " 0 "         " 35 "        " 903 "       " 1,306 "     " 259 "       " 314 "    
[12,] ""            ""            ""            ""            ""            ""         
[13,] " 5 "         " 32 "        " 37 "        " 10 "        " 5 "         " 53 "     
[14,] " 40 "        " 111 "       " 92 "        " 98 "        " 40 "        " 170 "    
[15,] " 27 "        " 213 "       " 154 "       " 197 "       " 173 "       " 268 "    
[16,] " 0 "         " 0 "         " 0 "         " 0 "         " 0 "         " 0 "      
[17,] " 0 "         " 0 "         " 0 "         " 91 "        " 0 "         " 0 "      
[18,] " 61,751 "    " 53,411 "    " 52,238 "    " 61,279 "    " 61,320 "    " 56,422 " 
[19,] " 2,466 "     " 591 "       " 1,092 "     " 1,518 "     " 2,896 "     " 2,937 "  
[20,] " 120 "       " 70 "        " 0 "         " 0 "         " 0 "         " 3 "      
[21,] " 0 "         " 33 "        " 0 "         " 0 "         " 0 "         " 0 "      
[22,] " 16,235 "    " 0 "         " 0 "         " 0 "         " 0 "         " 0 "      
[23,] " 155,996 "   " 173,895 "   " 151,542 "   " 1,385 "     " 873 "       " 212 "    
[24,] " 12,853 "    " 7,353 "     " 14,065 "    " 19,152 "    " 7,475 "     " 12,107 " 
[25,] " 0 "         " 0 "         " 0 "         " 0 "         " 0 "         " 0 "      
[26,] " 0 "         " 1,299 "     " 0 "         " 83 "        " 1,021 "     " 570 "    
[27,] ""            ""            ""            ""            ""            ""         
[28,] " 61,977 "    " 67,360 "    " 62,522 "    " 183,514 "   " 75,669 "    " 62,765 " 
[29,] " 0 "         " 1 "         " 0 "         " 0 "         " 0 "         " 0 "      
[30,] " 449,937 "   " 367,268 "   " 174,820 "   " 239,998 "   " 121,832 "   " 388,896 "
[31,] ""            ""            ""            ""            ""            ""         
[32,] " 0 "         " 0 "         " 0 "         " 0 "         " 0 "         " 0 "      
[33,] " 98 "        " 0 "         " 4 "         " 0 "         " 0 "         " 0 "      
[34,] " 0 "         " 0 "         " 0 "         " 0 "         " 0 "         " 0 "      
[35,] " 21 "        " 31 "        " 26 "        " 35 "        " 37 "        " 95 "     
[36,] " 0 "         " 0 "         " 0 "         " 7 "         " 0 "         " 0 "      
[37,] " 0 "         " 0 "         " 0 "         " 0 "         " 0 "         " 0 "      
[38,] " 0 "         " 0 "         " 0 "         " 0 "         " 0 "         " 0 "      
[39,] " 3,272,556 " " 7,585,263 " " 5,147,890 " " 2,685,152 " " 1,631,741 " " 60 "     
      [,10]         [,11]          [,12]          [,13]          [,14]         
 [1,] ""            ""             ""             ""             ""            
 [2,] ""            ""             ""             ""             ""            
 [3,] " 5,335 "     " 2,152 "      " 2,956 "      " 0 "          " 10,840"     
 [4,] " 969 "       " 221 "        " 666 "        " 0 "          " 1,856"      
 [5,] " 0 "         " 48 "         " 0 "          " 0 "          " 48"         
 [6,] " 0 "         " 15 "         " 0 "          " 0 "          " 15"         
 [7,] " 0 "         " 0 "          " 0 "          " 0 "          " 12"         
 [8,] " 0 "         " 0 "          " 0 "          " 0 "          " 234"        
 [9,] " 854 "       " 937 "        " 191 "        " 433 "        " 6,981"      
[10,] " 0 "         " 0 "          " 0 "          " 0 "          " 61"         
[11,] " 925 "       " 2,331 "      " 313 "        " 14 "         " 6,636"      
[12,] ""            ""             ""             ""             ""            
[13,] " 0 "         " 27 "         " 7 "          " 16 "         " 211"        
[14,] " 2 "         " 0 "          " 38 "         " 100 "        " 773"        
[15,] " 167 "       " 0 "          " 0 "          " 0 "          " 1,198"      
[16,] " 0 "         " 10 "         " 0 "          " 0 "          " 10"         
[17,] " 0 "         " 0 "          " 0 "          " 0 "          " 91"         
[18,] " 59,754 "    " 42,606 "     " 29,844 "     " 38,288 "     " 596,908"    
[19,] " 2,896 "     " 1,714 "      " 2,135 "      " 1,650 "      " 24,687"     
[20,] " 0 "         " 1,118 "      " 0 "          " 0 "          " 1,338"      
[21,] " 0 "         " 2 "          " 0 "          " 0 "          " 35"         
[22,] " 0 "         " 58,935 "     " 40,474 "     " 34,789 "     " 204,048"    
[23,] " 785 "       " 259,772 "    " 175,907 "    " 123,541 "    " 1,425,626"  
[24,] " 15,158 "    " 12,142 "     " 133 "        " 0 "          " 120,878"    
[25,] " 0 "         " 2 "          " 0 "          " 26 "         " 28"         
[26,] " 41 "        " 0 "          " 0 "          " 0 "          " 3,013"      
[27,] ""            ""             ""             ""             ""            
[28,] " 13,689 "    " 627 "        " 2,203 "      " 3,245 "      " 545,646"    
[29,] " 0 "         " 3,895 "      " 2,854 "      " 627 "        " 7,518"      
[30,] " 447,407 "   " 572,460 "    " 507,811 "    " 514,112 "    " 4,719,120"  
[31,] ""            ""             ""             ""             ""            
[32,] " 0 "         " 0 "          " 0 "          " 31 "         " 31"         
[33,] " 0 "         " 13 "         " 0 "          " 0 "          " 114"        
[34,] " 50 "        " 0 "          " 0 "          " 0 "          " 320"        
[35,] " 30 "        " 75 "         " 22 "         " 25 "         " 585"        
[36,] " 30 "        " 0 "          " 0 "          " 0 "          " 75"         
[37,] " 304 "       " 50 "         " 70 "         " 0 "          " 424"        
[38,] " 0 "         " 0 "          " 0 "          " 0 "          " 3"          
[39,] " 2,041,590 " " 11,331,996 " " 34,792,518 " " 39,050,200 " " 147,491,553"

[[5]]
      [,1]                                                       [,2]           [,3]          
 [1,] "alifornia Waters"                                         ""             ""            
 [2,] "Mollusks"                                                 ""             ""            
 [3,] "Whelk, Kellet's................................... "      " 1,417 "      " 1,186 "     
 [4,] "Waters Area Total: "                                      " 27,795,893 " " 17,662,015 "
 [5,] "ther Waters"                                              ""             ""            
 [6,] "Fishes"                                                   ""             ""            
 [7,] "Dolphin (fish)................................ "          " 0 "          " 0 "         
 [8,] "Escolar.............................................. "   " 68 "         " 65 "        
 [9,] "Oilfish................................................ " " 0 "          " 0 "         
[10,] "Scorpionfish, California..................... "           " 0 "          " 0 "         
[11,] "Shark, shortfin mako......................... "           " 480 "        " 0 "         
[12,] "Shark, thresher.................................. "       " 0 "          " 0 "         
[13,] "Sheephead, California....................... "            " 0 "          " 0 "         
[14,] "Swordfish.......................................... "     " 15,100 "     " 10,227 "    
[15,] "Tuna, albacore.................................. "        " 3,072 "      " 253 "       
[16,] "Tuna, bigeye..................................... "       " 6,674 "      " 2,865 "     
[17,] "Tuna, bluefin..................................... "      " 1,585 "      " 256 "       
[18,] "Tuna, yellowfin.................................. "       " 0 "          " 0 "         
[19,] "Wahoo............................................... "    " 0 "          " 0 "         
[20,] "Crustaceans"                                              ""             ""            
[21,] "Lobster, California spiny.................... "           " 0 "          " 0 "         
[22,] "Prawn, ridgeback.............................. "          " 0 "          " 0 "         
[23,] "Waters Area Total: "                                      " 26,979 "     " 13,666 "    
[24,] "Grand Total: "                                            " 27,822,872 " " 17,675,681 "
      [,4]          [,5]          [,6]          [,7]          [,8]          [,9]         
 [1,] ""            ""            ""            ""            ""            ""           
 [2,] ""            ""            ""            ""            ""            ""           
 [3,] " 2,353 "     " 1,811 "     " 1,640 "     " 1,616 "     " 1,734 "     " 3,915 "    
 [4,] " 4,364,537 " " 8,923,809 " " 6,905,513 " " 5,318,798 " " 3,087,396 " " 2,954,437 "
 [5,] ""            ""            ""            ""            ""            ""           
 [6,] ""            ""            ""            ""            ""            ""           
 [7,] " 0 "         " 0 "         " 897 "       " 0 "         " 590 "       " 0 "        
 [8,] " 0 "         " 0 "         " 338 "       " 0 "         " 0 "         " 0 "        
 [9,] " 0 "         " 0 "         " 0 "         " 0 "         " 55 "        " 0 "        
[10,] " 0 "         " 0 "         " 0 "         " 0 "         " 0 "         " 0 "        
[11,] " 1,289 "     " 0 "         " 15 "        " 0 "         " 127 "       " 0 "        
[12,] " 0 "         " 0 "         " 0 "         " 0 "         " 0 "         " 0 "        
[13,] " 0 "         " 0 "         " 0 "         " 0 "         " 0 "         " 0 "        
[14,] " 10,750 "    " 0 "         " 6,813 "     " 0 "         " 1,690 "     " 0 "        
[15,] " 0 "         " 0 "         " 145 "       " 0 "         " 8,080 "     " 0 "        
[16,] " 1,875 "     " 0 "         " 3,296 "     " 0 "         " 656 "       " 0 "        
[17,] " 0 "         " 0 "         " 0 "         " 0 "         " 0 "         " 0 "        
[18,] " 369 "       " 0 "         " 29 "        " 0 "         " 35 "        " 0 "        
[19,] " 0 "         " 0 "         " 0 "         " 0 "         " 27 "        " 0 "        
[20,] ""            ""            ""            ""            ""            ""           
[21,] " 0 "         " 0 "         " 0 "         " 0 "         " 0 "         " 0 "        
[22,] " 0 "         " 0 "         " 0 "         " 0 "         " 0 "         " 0 "        
[23,] " 14,283 "    " 0 "         " 11,533 "    " 0 "         " 11,260 "    " 0 "        
[24,] " 4,378,820 " " 8,923,809 " " 6,917,046 " " 5,318,798 " " 3,098,656 " " 2,954,437 "
      [,10]         [,11]          [,12]          [,13]          [,14]         
 [1,] ""            ""             ""             ""             ""            
 [2,] ""            ""             ""             ""             ""            
 [3,] " 2,888 "     " 1,033 "      " 2,745 "      " 4,916 "      " 27,253"     
 [4,] " 3,429,525 " " 13,290,556 " " 37,357,055 " " 40,243,170 " " 171,332,704"
 [5,] ""            ""             ""             ""             ""            
 [6,] ""            ""             ""             ""             ""            
 [7,] " 0 "         " 1,576 "      " 0 "          " 0 "          " 3,063"      
 [8,] " 0 "         " 90 "         " 0 "          " 120 "        " 681"        
 [9,] " 0 "         " 0 "          " 0 "          " 300 "        " 355"        
[10,] " 0 "         " 0 "          " 7 "          " 0 "          " 7"          
[11,] " 0 "         " 682 "        " 0 "          " 510 "        " 3,103"      
[12,] " 20 "        " 0 "          " 0 "          " 0 "          " 20"         
[13,] " 0 "         " 0 "          " 10 "         " 0 "          " 10"         
[14,] " 0 "         " 12,333 "     " 0 "          " 8,108 "      " 65,021"     
[15,] " 0 "         " 1,006 "      " 0 "          " 1,814 "      " 14,370"     
[16,] " 0 "         " 1,243 "      " 0 "          " 981 "        " 17,590"     
[17,] " 0 "         " 186 "        " 0 "          " 0 "          " 2,027"      
[18,] " 0 "         " 0 "          " 0 "          " 0 "          " 433"        
[19,] " 0 "         " 0 "          " 0 "          " 0 "          " 27"         
[20,] ""            ""             ""             ""             ""            
[21,] " 0 "         " 0 "          " 58 "         " 0 "          " 58"         
[22,] " 0 "         " 838 "        " 0 "          " 0 "          " 838"        
[23,] " 20 "        " 17,954 "     " 75 "         " 11,833 "     " 107,603"    
[24,] " 3,429,545 " " 13,308,510 " " 37,357,130 " " 40,255,003 " " 171,440,307"
x
View(x)
Q
LS0tCnRpdGxlOiAiYWhub2xkX2xhYmJvb2siCmF1dGhvcjogIkRhbiBPdmFuZG8iCmRhdGU6ICJEZWNlbWJlciAxNCwgMjAxNiIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCi0tLQoKYGBge3IgbGlicmFyaWVzLCBlY2hvPUYsIG1lc3NhZ2U9Riwgd2FybmluZz1GLCBpbmNsdWRlPUZ9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGZvcmNhdHMpCmxpYnJhcnkocnN0YW5hcm0pCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KGdnc2NpKQpsaWJyYXJ5KGJyb29tKQpsaWJyYXJ5KGNhcikKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KHJ2ZXN0KQoKZGVtb25zOjpsb2FkX2Z1bmN0aW9ucyhmdW5jX2RpciA9ICcuLi9mdW5jdGlvbnMnKQoKYGBgCgpBIHJ1bm5pbmcgbGFiYm9vayBmb3IgaWRlYXMgaW4gdGhlIEFobm9sZCBwcm9qZWN0CgojIyBCaW9yZWdpb25zCgpMb29raW5nIGF0IEBIYW1pbHRvbjIwMTAsIGJpb3JlZ2lvbnMgY2xlYXJseSBwbGF5IGEgcm9sZS4gWW91IGNvdWxkIGluY2x1ZGUgdGhlbSBzaW1wbHkgYXMgY292YXJpYXRlcy4gQnV0LCB0aGF0IGRvZXNuJ3QgYWNjb3VudCBmb3IgdGhlIHBvdGVudGlhbCBpbnRlcmFjdGlvbnMgYmV0d2VlbiBNUEFzIGFuZCByZWdpb25zLiBNaWdodCBuZWVkIHRvIGVpdGhlciBydW4gdGhlbSBhcyBzZXBlcmF0ZSBtb2RlbHMgKHdvcnRoIGl0IHRvIHNlZSksIHdpdGggaW50ZXJhY3Rpb24gZWZmZWN0cyB3aXRoIE1QQSB0byBzZWUgaWYgdGhlcmUgYXJlIGRpZmZlcmVuY2VzIGFtb25nIGJpb3JlZ2lvbnMgaW4gTVBBIGVmZmVjdHMKCiMjIEludGVyc3BlY2llcyBJbnRlcmFjdGlvbnMKCkNhbiB5b3UgbG9vayBhdCB0aGUgc3BhdGlhbC1jb3ZhcmlhbmNlIG1hdHJpeCBvZiB0aGVzZSBzcGVjaWVzPwoKT3IgaXMgdGhlcmUgZW5vdWdoIGRhdGEgdG8gc3VnaWhhcmEgdGhlIGRhbW4gdGhpbmcsIGFuZCBhc2sgd2hldGhlciBzb21lIHNwZWNpZXMgc2VlbSB0byBjYXVzZSBkZWNyZWFzZXMgaW4gb3RoZXJzPwoKIyMgTGFuZGluZ3MgZGF0YQoKKltDYW4gYmUgZm91bmQgaGVyZV0oaHR0cHM6Ly93d3cud2lsZGxpZmUuY2EuZ292L0Zpc2hpbmcvQ29tbWVyY2lhbC9MYW5kaW5ncyMyNjAwNDEzNzUtMjAxNSkKKiBDYW4gcHJldHR5IGVhc2lseSBmaWd1cmUgb3V0IGEgd2F5IHRvIHNjcmFwZSBhbGwgdGhpcwoKCiMjIEZpeGVkIGVmZmVjdHMsIHJhbmRvbSBlZmZlY3RzLCBhbmQgZXJyb3JzIGluIHZhcmlhYmxlcywgYW5kIGNsdXN0ZXJpbmcKCkl0J3MgaW1wb3J0YW50IHRoYXQgeW91IGdldCB0aGlzIHN0cmFpZ2h0ZW5lZCBvdXQuIAoKVGhlICJlcnJvcnMgaW4gdmFyaWFibGVzIiByZWxhdGVzIHRvIHRoZSBpZGVhIHRoYXQgeW91ciBjb3ZhcmlhdGUgZGF0YSBhcmUgbm93IHJhbmRvbSBkcmF3cyBmcm9tIHNvbWUgZGlzdHJpYnV0aW9uLiBTbywgZm9yIGV4YW1wbGUsIHlvdSBvYnNlcnZlIGxlbmd0aCBkYXRhLCB3aGljaCB5b3UgZml0IHRvIGEgbW9kZWwgdGhhdCBwcmVkaWN0cyBsZW5ndGggZGF0YSBhbmQgYSBzdGFuZGFyZCBkZXZpYXRpb24sIGFuZCB5b3UgcGFzcyB0aG9zZSBwcmVkaWN0ZWQgbGVuZ3RoIGRhdGEgdG8gc29tZSBvdGhlciBwYXJ0IG9mIHRoZSBtb2RlbC4gU2VlIGJveCA2LjIuMiBpbiBiYXllc2lhbiBwcmltZXIuIFRoaXMgaXMganVzdCBiYXNpY2FsbHkgc2F5aW5nIGFzIGFub3RoZXIgcmFuZG9tIHZhcmlhYmxlIGluIHRoZSBsaWtsaWhvb2QsIGluc3RlYWQgb2YgdGFraW5nIGl0IGFzIGdpdmVuICh3aGVyZSB5b3Ugd291bGQganVzdCB1c2UgdGhlIGxlbmd0aCBkYXRhKQoKQmFzaWNhbGx5LCB3aGF0IEknbSB0cnlpbmcgdG8gZmlndXJlIG91dCBoZXJlIGlzIGhvdyB0byBwcm9wZXJseSBkZWFsIHdpdGggdGhlIHRoZSBjbHVzdGVyaW5nIG9mIHRoZSBkYXRhIGluIHRoZSB0aW1lIHNlcmllcy4gU28sIGZvciBhbnkgY2F0ZWdvcmljYWwgdmFyaWFibGUgdGhhdCBpcyBhdCBhIGhpZ2hlciBsZXZlbCB0aGFuIHRoZSBkYXRhLCBpdCBzZWVtcyByZWFzb25hYmxlIHRvIGp1c3QgZ2l2ZSBpdCBhIHByaW9yIChlLmcuIGFsbCB0aGUgeWVhciBjb2VmZmljaWVudHMgc2hhcmUgYSBjb21tb24gcHJpb3IpLCBhbGwgdGhlIHNwZWNpZXMgZWZmZWN0cyBzaGFyZSBhIHByaW9yIGJ5IGdyb3VwLCBldGMsIHdoZXJlIGFsbCBvZiB0aG9zZSBzaGFyZSBhIGNvbW1vbiBwcmlvci4gCgpXaGF0IGRvIHlvdSBkbyBhYm91dCB0aGluZ3MgbGlrZSBsaW5mIHRob3VnaD8gUmVwZWF0ZWQgYSB3aG9sZSB0b24gb3ZlciB0aW1lLCBidXQgeW91IGNhbid0IGp1c3QgZ2l2ZSBpdCBhIGhpZXJhcmNoaWNhbCBwcmlvci4uLi4gTG9va2luZyBhdCBHZWxtYW4gYW5kIEhpbGwKCgpPT09PT09PSEhISEhILCBtYXliZSB0aGlzIGlzIHRoZSByaWdodCBhcHByb2FjaC4gR2l2ZSBpdCBzcGVjaWVzIGZpeGVkIGVmZmVjdHMsIGFuZCB0aGVuIG1ha2UgdGhlIHNwZWNpZXMgZml4ZWQgZWZmZWN0cyBhIHJlZ3Jlc3Npb24gb2Ygc3BlY2llcyBlZmZlY3RzIGNvZWZmaWNpZW50cyBvbiBsaWZlIGhpc3RvcnkgdHJhaXRzLiBTbywgYSBtdWx0aS1sZXZlbCBtb2RlbGluZyBhcHByb2FjaCwgbGlrZSBHZWxtYW4gYW5kIEhpbGwgcGFnZSAyNDEuIAoKRnJvbSBhIGhpZXJhcmNoaWNoYWwgcGVyc3BlY3RpdmUgdGhlbiwgdGhlIGlkZWEgaXMgbm93IHRvIHRoaW5rIG9mIHRoZXNlIGFzIGEgYnVuY2ggb2YgbmVzdGVkIHJlZ3Jlc3Npb25zIGZvciBlYWNoIGxldmVsIG9mIHRoZSBkYXRhLCB3aXRoIHRoZSByaWdodCByYW5kb20gZWZmZWN0cyBsaW5raW5nIGVhY2ggbGF5ZXIgdG9nZXRoZXIuIAoKU28sIHlvdSBoYXZlIHllYXIgdGVybXMsIGFuZCB0aG9zZSB5ZWFyIHRlcm1zIGFyZSBhIGZ1bmN0aW9uIG9mIHllYXJseSB0aGluZ3MgbGlrZSB0ZW1wZXJhdHVyZSBhbmQgZWwgbmnDsW8sIHNwZWNpZXMgdGVybXMsIGV0Yy4gVGhlIHByb2JsZW0gdGhhdCB5b3UndmUgYmVlbiBoYXZpbmcsIGFuZCB0aGlzIHByb2JhYmx5IGV4cGxhaW5zIHNvbWUgb2YgdGhlIGNvbnZlcmdhbmNlIGlzc3VlcywgaXMgdGhhdCB5b3UgaGF2ZSBtYXNzaXZlIGNvbGluZWFyaXR5IHdoZW4geW91IHRyeSBhbmQgaW5jbHVkZSBmaXhlZCBlZmZlY3RzIGZvciB0aGluZ3MgbGlrZSBzcGVjaWVzLCBhbmQgdGhlbiB0aGUgY292YXJpYXRlcyBhdCB0aGUgc3BlY2llcyBsZXZlbD8gU28sIHRoaXMgYWxsb3dzIHlvdSB0byBzb3J0IG9mIGdldCB0aGUgYmVzdCBvZiBib3RoIHdvcmxkcywgd2hlcmUgeW91IG5vdyBnZXQgdGhlICJpbnRlcmNlcHRzIiBieSB0aGUgcmlnaHQgdGhpbmcsIGJ1dCB0aG9zZSBpbnRlcmNlcHRzIHRha2UgaW50byBhY2NvdW50IHRoZSBkYXRhIGF0IHRoZSBpbnRlcmNlcHQgbGV2ZWwgdGhhdCB5b3UgaGF2ZSB0aGF0IGNhbiBpbmZsdWVuY2UgdGhlIG91dGNvbWUuIFNvIGl0IGxvb2tzIHRob3VnaCBmcm9tIEdlbG1hbiBhbmQgSGlsbCBwYWdlIDI4MSB0aGF0IHRvIGRvIHRoaXMsIHlvdSBkb24ndCBoYXZlIHRvIGluY2x1ZGUgdGhvc2UgdGVybXMgaW4gdGhlIG1peGVkIGVmZmVjdHMgcGFydCBvZiB0aGUgcmVncmVzc2lvbiBpdHNlbGYsIGJ1dCBvbmx5IHB1dCB0aGVtIGluLCBidXQgd2l0aCB0aGUgYXBwcm9wcmlhdGUgcHJpb3JzLiBTbywgdGhhdCdzIHdoZXJlIHRoZSBjb21tb24gcHJpb3IgY29tZXMgaW4/IFlvdSdsbCBqdXN0IG5lZWQgdG8gbWVzcyB3aXRoIHRoaXMgb25lIHdpdGggY29kZSBvbmNlIHlvdSBjYW4gY29kZSBpdCBpbiBTVEFOCgpZb3Ugc2hvdWxkIHRlc3QgdGhpcyBieSBnZXR0aW5nIHRoZSB0aGluZyB3cml0dGVuIGluIFNUQU4sIGFuZCBjb21wYXJpbmcgdHdvIHZlcnNpb25zLCBvbmUgd2hlcmUgeW91IGRvIGl0IHRoZSB1c3VhbCB3YXkgKGVzdGltYXRlIHRoZSBtZWFuIG9mIHRoZSBwcmlvciksIG9uZSB3aGVyZSB5b3UgaW5jbHVkZSBjb3ZhcmlhdGVzIGluIHRoZSBtb2RlbCwgdGhlIG90aGVyIHdoZXJlIHlvdSBmaXQgdGhlbSBzZXBlcmF0ZWx5CgogIEFIQUBAISFAISNAIUAjISBUSEFUJ1MgV0hZIFRIRSBNRUFOIE9GIFRIRSBQUklPUiBJUyAwISEhISB0aGluayBhYm91dCBpdC4gU2F5IHlvdSB3YW50IHRvIGluY2x1ZGUgZml4ZWQgZWZmZWN0cyBmb3IgZWFjaCBzaXRlLiBVbmRlciB0aGUgbW9kZWwgYXMgaXQgZ2V0J3Mgd3JpdHRlbiBhbGwgb3ZlciB0aGUgcGxhY2UgaGVyZSwgdGhleSBhcmUgZGlzdHJpYnV0ZWQgd2l0aCBtZWFuKHUsc2lnbWEpLiBOb3csIHdoZW4geW91IGluY2x1ZGUgdGhlIGZpeGVkIGVmZmVjdHMgbWVhbiBpbiB0aGF0IGNvbnRleHQ6IHRob3NlIGFyZSBkZXZpYXRpb25zIGZyb20gYSBtZWFuIDAhIFNvLCB5b3UndmUgYWxyZWFkeSBhY2NvdW50ZWQgZm9yIHRoZSBjaGFuZ2UgZnJvbSB0aGUgbWVhbiBlZmZlY3QgYnkgaW5jbHVkaW5nIHRoZSBpbnRlcmNlcHQuIElmIHlvdSB0aGVuIHNheSBpbmNsdWRlIHNpdGUgc3BlY2lmaWMgdGVtcGVyYXR1cmUgaW4gdGhlcmUsIHlvdSdkIGp1c3QgY2h1Y2sgaXQgaW4gYXMgYSB2YXJpYWJsZSwgd2hpY2ggd291bGQgZG8gdGhlIGV4YWN0IHNhbWUgdGhpbmcgYXMgc2F5aW5nIE4oc2l0ZSArIHRlbXAsc2lnbWEpLCBvciBzaXRlICsgdGVtcCArIG4oMCxzaWdtYSkuIEFsbCB0aG9zZSB0ZXJtcyBhcmUgZ2V0dGluZyBzb2FrZWQgdXAgaW4gdGhlIGludGVyY2VwdC4gU3VwcG9zZSB0aGF0IGl0IHNob3VsZCBiZSBOKC4yLHNpZ21hKS4gU28sIG5vIG1hdHRlciB3aGF0LCBldmVyIHllYXIgdGVybSBpcyBnb2luZyB0byBiZSAuMiArLSBzb21lIHRlcm0uIFRoYXQgaXMgdGhlIHNhbWUgdGhlbiBhcyBqdXN0IGFkZGluZyAuMiB0byB0aGUgaW50ZXJjZXB0LCBhbmQgdGhlbiBzZXR0aW5nIHRoZSBtZWFuIG9mIHRoZSBwcmlvciB0byAwLiBTbywgdGhleSByZWFsIGtleSBoZXJlIHRoZW4gaXMgc2ltcGx5IHNwZWNpZnlpbmcgdGhlIGdyb3VwLWxldmVsIHN0YW5kYXJkIGRldmlhdGlvbi4gV293LiAKCgoKKipFdmVyeXRoaW5nIGlzIGEgcmFuZG9tIGVmZmVjdCBpbiBiYXllcywgdGhlIGtleSBpcyBpcyBpdCBncm91cGVkKioKCiMjIE1vZGVsIFN0cnVjdHVyZQoKTGV0J3MgZ28gdGhyb3VnaCB0aGUgdGhpbmcgZnJvbSBzY3JhdGNoIGFuZCB0aGluayB0aHJvdWdoIGhvdyB5b3Ugd2FudCB0aGlzIHRoaW5nIHRvIGxvb2ssIGZyb20gYSBtb2RlbCBkaWFncmFtbWluZyBwZXJzcGVjdGl2ZS4gCgojIyMgSHVyZGxlIGNvbXBvbmVudAoKIyMjIERhdGEKClNvIG1heSBiZSB5b3UgbmVlZCB0byBiZSB0aGlua2luZyBhYm91dCB0aGlzIGtpbmQgb2YgbGlrZSBhIENQVUUgc3RhbmRhcmRpemF0aW9uLCB3aGVyZSBvbiBvbmUgaGFuZCB5b3UncmUgZml0dGluZyBhIHBvaXNzb24gZGlzdHJpYnV0aW9uIHRvIHRoZSB0cmFuc2VjdCBkYXRhLCBhbmQgdXNpbmcgdGhhdCB0byBlc3RpbWF0ZSBkZW5zaXRpZXMsIGJhc2VkIG9uIGRldGVybWluaXN0aWMgZXF1YXRpb25zIGFuZCBhIHNpZ21hIChvciBtYXliZSB0cmVhdGluZyB0aGF0IHBhcnQgYXMgZGF0YSB0byBtYWtlIHRoaW5ncyBhIGJpdCBlYXNpZXIpLCBhbmQgdGhlbiBmaXR0aW5nIHRoZSByZWdyZXNzaW9uIHRvIHRob3NlIGRlbnNpdGllcy4gVGhlIGNoYWxsZW5naW5nIHBhcnQgaXMgaG93IHlvdSByYXRpb25hbGl6ZSB0aGUgdHdvIGRpc3RyaWJ1dGlvbnMgZm9yIGRlbnNpdHk7IHRoYXQgaW1wbGllZCBieSB0aGUgcmVncmVzc2luIGFuZCB0aGF0IGltcGxpZWQgYnkgdGhlIGVycm9yIGZyb20gdGhlIGxvZ2l0IG1vZGVsIAoKQUhBLCBzbyB0aGUga2V5IGhlcmUgaXMgdGhpbmtpbmcgYWJvdXQgdGhlIG1hcmdpbmFsIHBvc3RlcmlvciBvZiB0aGUgcmVncmVzc2lvbiBjb2VmZmljaWVudHMsIG5vdCBqdXN0IHRoZSByZWdyZXNzaW9uIGNvZWZmaWNpZW50cy4gVGhlIHNpZ21hIG9mIHRoZSByZWdyZXNzaW9uIG1vZGVsIHVzIHNheWluZyB0YWtpbmcgdGhvc2UgZGF0YSBhcyBvYnNlcnZhdGlvbnMgZnJvbSBhIHJhbmZvbSBldmVudCwgaG93IHdlbGwgZG9lcyB0aGUgbW9kZWwgZXhwbGFpbiB0aGF0LiBCdXQsIHRoYXQncyBqdXN0IHVuZGVyIHRoYXQgb25lIHNjZW5hcmlvLiBTbywgaWYgeW91IHdlcmUgZG9pbmcgdGhpcyBpbiBhIHNpbXBsZSB3YXkgd2hlcmUgdGhlIHBvc3RlcmlvciBpcyBhbmFseXRpY2FsLCB0aGVuIHlvdSBnZXQgdGhlIGJldGFzIG91dC4gQnV0LCB0aGUgZnVsbCBtYXJnaW5hbCBub3cgd291bGQgdGFrZSBpbnRvIGFjY291bnQgdGhlIHJhbmdlIG9mIHdvcmxkcyB0aGF0IHRoZSBkZW5zaXRpZXMgY291bGQgbGl2ZSBpbiwgc28geW91J2Qgc2FtcGxlIGZyb20gdGhlIGpvaW50IHBvc3RlcmlvciB0byBnZXQgdGhlIGJldGFzIG9mIGludGVyZXN0IQoKIyMjIFByb2Nlc3MKClNlZSBib3ggNi4yLjIgaW4gYSBCYXllc2lhbiBQcmltZXIgZm9yIGlkZWFzIG9uIHRoaXMuIAoKVGhlIHdheSBJJ20gbGVhbmluZyB0b3dhcmRzIGlzIHNvbWV0aGluZyBsaWtlIHRoaXM6IFRoZXJlIGlzIGEgdHJ1ZSBiaW9tYXNzIHRoYXQgaXMgYSByYW5kb20gZHJhdyBmcm9tIGEgZGlzdHJpYnV0aW9uIHdpdGggbWVhbiBvYnNlcnZlZCBiaW9tYXNzIGFuZCBhIHZhcmlhbmNlIGRlZmluZWQgYnkuLi4uIHNvbWV0aGluZyAob2JzZXJ2ZXIsIGdyb3VwLCBhIGZ1bmN0aW9uIG9mIGtlbHAsIHZpcywgZXRjLikuIFRoZSBpbnZlcnNlIG9mIHRoYXQsIHRoYXQgdGhlIG9ic2VydmVkIGFyZSBhIHJhbmRvbSBkcmF3IGZyb20gc29tZSB0cnVlIGRpc3RyaWJ1dGlvbiB3aXRoIG1lYW4gdHJ1ZSBhbmQgc2lnbWEgYWJvdmUgc2VlbXMgaGFyZCB0byBkbyBpbiB0aGlzIGNvbnRleHQ6IHlvdSdkIGhhdmUgdG8gZml0IGEgbWFzc2l2ZSBudW1iZXIsIG9yIHBvc3NpYmx5IGFuIHVuaWRlbnRpZmlhYmxlIG51bWJlciwgb2YgbWVhbnMsIHVubGVzcyB5b3Ugd2FudCB0byBzYXkgdGhhdCB0aGF0IHRoZXJlJ3Mgc29tZSBjbHVzdGVyaW5nIChlLmcuIG1lYW4gYnkgc3BlY2llcyBieSBzaXRlIGJ5IHllYXIsIHdoaWNoIEkgdGhpbmsgYXJlIHRoZSByYXcgYWdncmVnYXRpb24gYW55d2F5cykuIAoKQWggd2FpdCwgeW91J3JlIG1ha2luZyB0aGlzIHdheXl5eSB0byBjb21wbGljYXRlZC4gVGhlIHRoaW5nIHlvdSdyZSB0aGlua2luZyBhYm91dCBoZXJlIGFyZSBlcnJvcnMgaW4gKipwcmVkaWN0b3IqKiB2YXJpYWJsZXMsIG5vdCBkZXBlbmRlbnQgdmFyaWFibGVzIGxpa2UgdGhlIGRlbnNpdHksIHdoaWNoIGlzIHdoYXQgeW91J3JlIHRyeWluZyB0byBleHBsYWluLiBVbmRlciBhIHRyYWRpdGlvbmFsIEJheWVzaWFuIGZyYW1ld29yaywgdGhlIGRlcGVuZGVudCB2YXJpYWJlbHMgYXJlIGFscmVhZHkgY29uc2lkZXJlZCByYW5kb20gZHJhd3MgKHVudGlsIHRoZXkgYXJlIG9ic2VyZWQpLCB3aGlsZSB0aGUgcmVzdCBhcmUgY29uc2lkZXJlZCBkYXRhLiBCdXQsIHRoZSBzdHVmZiB5b3Ugd2VyZSB0aGlua2luZyBvZiB0aGVyZSBhcmUgZm9yIGluZGVwZW5kZW50IHZhcmlhYmxlcywgdGhpbmdzIGxpa2UgdGVtcGVyYXR1cmUuIFNvLCB5b3UgY291bGQgc2F5IHRoYXQgdGVtcGVyYXR1cmUgaXMgaW1wZXJmZWN0eWwgbWVhc3VyZWQsIGFuZCBjb21lcyBmcm9tIGEgZGlzdHJpYnV0aW9uIHdpdGggc29tZSB0cnVlIG1lYW4gYW5kIHNpZ21hLiAKClNvLCB5b3UgZG9uJ3QgbmVlZCB0byBtZXNzIHdpdGggdGhlICJlcnJvcnMiIGluIGRlbnNpdHksIHNpbmNlIGl0J3MgYWxyZWFkeSBjb25zaWRlcmVkIGEgcmFuZG9tIGRyYXcsIGZyb20gYSBkaXN0cmlidXRpb24gd2l0aCBtZWFuIGV4cGVjZWQgZGVuc2l0eSBmcm9tIHRoZSBtb2RlbCBpdHNlbGYsIGFuZCBhIHNpZ21hIGVzdGlhbXRlZCBieSB0aGUgbW9kZWwuIAoKTm93LCB3aGVyZSB0aGluZ3MgY291bGQgdGhlbiBnZXQgaW50ZXJlc3RpbmcgaXMgdXNpbmcgYSBtb2RlbCB0byBlc3RpbWF0ZSB0aGUgc2lnbWFzLiBpLmUuIHNpZ21hIGlzIGEgbGluZWFyIGZ1bmN0aW9uIG9mIHNheSBhIGNvbnN0YW50LCBwbHVzIGtlbHAgY292ZXIgKyB2aXMgKyByZXNlYXJjaCBncm91cC4uLiBldGMuIAoKTm93LCB0aGF0J3MgYWxsIGFzc3VtaW5nIHRoYXQgdGhlIGJpb21hc3MgZGVuc2l0aWVzIGFyZSBpbiBmYWN0IHlvdXIgZGF0YS4gVGhlcmUncyBhbm90aGVyIHdheSB5b3UgY291bGQgZG8gdGhpcywgc29tZXdoYXQgc2ltaWxhciB0byBAS2FybmF1c2thczIwMTEuIFRoZSBpZGVhIGhlcmUuIHlvdSBoYXZlICoqdHdvKippc2ggZGF0YSBzb3VyY2VzLiBPbmUgYXJlIHRoZSBhY3R1YWwgbGVuZ3Rocy4gVGhlIG90aGVyIGFyZSB0aGUgb2JzZXJ2ZWQgZGVuc2l0aWVzLiBUaGUgZ29hbCBpcyBzdGlsbCB0byBmaXQgYSByZWdyZXNzaW9uIHRvIHRoZSBkZW5zaXRpZXMuIFRoZSBpc3N1ZSBub3cgdGhvdWdoIGlzIHRoYXQgeW91J3JlIGdvaW5nIHRvIGZpdCB0aGUgcmVncmVzc2lvbiB0byBkZW5zaXRpZXMgZXN0aW1hdGVkIGZyb20gdGhlIHJhdyBsZW5ndGggZGF0YS4gU28sIHlvdSdkIHRha2UgdGhlIGxlbmd0aCBkYXRhLiBZb3UnZCB0aGVuIHVzZSB0aGF0IGxlbmd0aCBkYXRhIHRvIGJ1aWxkIHVwIGEgbW9kZWwgb2YgZGVuc2l0aWVzIHRoYXQgeW91IHRoZW4gZml0IHRoZSByZWdyZXNzaW9uIG9uLiBUaGUgcHJvYmxlbSBpcywgeW91J2QgbmVlZCBhIG1vZGVsIHJlbGF0aW5nIHNvbWV0aGluZyBiYWNrIHRvIHRoZSBsZW5ndGggZGF0YSwgd2hpY2ggeW91IGFyZW4ndCByZWFsbHkgZG9pbmcgaGVyZS4gaS5lIHdoYXQgd291bGQgdGhlIGxlbmd0aHMgYmUgY29uZGl0aW9uYWwgb24/IEFsdGVybmF0aXZlbHksIHlvdSB0cmVhdCB0aGUgbGVuZ3RocyBhcyBkYXRhLCBhbmQgdGhlIGRlbnNpdGllcyBhcyByYW5kb20gdmFyaWFibGVzLiBOb3csIHlvdSBoYXZlIHRoZSBvYnNlcnZlZCBkZW5zaXRpZXMsIHRoYXQgYXJlIGRyYXdzIGZyb20gYSBkaXN0cmlidXRpb24gd2l0aCBtZWFuIG9mIHByZWRpY3RlZCBkZW5zaXR5LCB3aGVyZSBwcmVkaWN0ZWQgZGVuc2l0eSBpcyBhIGZ1bmN0aW9uIG9mIHRoZSBsZW5ndGhzPyBUaGF0IGlzIGEgYml0IG9mIGRvdWJsZSBkaXBwaW5nIHRob3VnaC4gTm93IG9uZSBvcHRpb24gY291bGQgYmUgdG8gdHJhaW4gdGhlIHJlZ3Jlc3Npb24gb24gImRlbnNpdHkiIGRhdGEgZ2VuZXJhdGVkIGZyb20gdGhlIGxlbmd0aHMuIFNvIG5vdywgeW91IHNheSB0aGUgb2JzZXJ2ZWQgZGVuc2l0aWVzIGFyZSBkcmF3biBmcm9tIGEgZGlzdHJpYnV0aW9uIHByZWRpY3RlZCBieSB0aGUgcmVncmVzc2lvbiwgd2hlcmUgdGhlIHJlZ3Jlc3Npb24gaXMgdHJhaW5lZCBvbiB0aGUgZXhwZWN0ZWQgZGVuc2l0aWVzIHByZWRpY3RlZCBmcm9tIHRoZSBsZW5ndGggZGF0YSwgZXN0aW1hdGluZyBzaWdtYXMgYWxsIHRoZSB3YXkuIFRoaXMgc2VlbXMgbWF5YmUgdGhlIG1vc3Qgcm9idXN0IG9wdGlvbiwgYnV0IGFsc28gYSByb3lhbCBwYWluIGluIHRoZSBhc3MuIEFuZCBkbyB5b3UgcmVhbGx5IGdhaW4gYSB3aG9sZSBsb3QgZnJvbSB0aGF0PwoKSXQgc2VlbXMgbGlrZSB5b3UgaGF2ZSBzb21ldGhpbmcgbGlrZSB0aHJlZSBkaWZmZXJlbnQgbW9kZWwgc3RydWN0dXJlcyBhbGwgbW9kZWxzIGNhbiBzaGFyZSBhIGNvbW1vbiBoaWVyYXJjaGljYWwgbmF0dXJlIHRvIHRoZSBkYXRhLCB0aGUgcXVlc3Rpb24gcmVhbGx5IGlzIGhvdyBkbyB5b3Ugd2FudCB0byBtb2RlbCBlcnJvcnMsIGVzcGVjaWFsbHkgY29uZGl0aW9uYWwgb24gd2hhdCB5b3UgcmVhbGx5IGNhcmUgYWJvdXQgYXJlIGRvaW5nIGEgZ29vZCBqb2Igb24gdGhlIGVzdGltYXRvcnMsIG5vdCBvbiB0aGUgb3V0LW9mLXNhbXBsZSBwcmVkaWN0aW9uCgoxLiBUaGUgc3RhbmRhcmQgbW9kZWwsIHdpdGggcG90ZW50aWFsIGZvciBjbHVzdGVyaW5nIG9mIGVycm9ycyBpbiBkZW5zaXRpZXMgYXMgYSBmdW5jdGlvbiBvZiBhcHByb3ByaWF0ZSBsZXZlbHMgKGUuZy4gc3BlY2llcyBncm91cHMsIGV0Yy4gKS5UaGF0J3MgcmVhbGx5IHdoYXQgZXF1YXRpb24gNi4yLjUxIGluIEJQIGlzIGRvaW5nOiBtYWtpbmcgYSBtb3JlIGNvbXBsZXggbW9kZWwgb2YgdGhlIGVycm9yIHN0cnVjdHVyZSBhc3NvY2lhdGVkIHdpdGggdGhlIG9ic2VydmF0aW9ucy4gCgoyLiBBIG1vZGVsIGZvciBzdGFuZGFyZCBkZXZpYXRpb25zIGluIHRoZSBkZW5zaXRpZXMsIHdoZXJlIHNpZ21hIGlzIGEgbGluZWFyIGZ1bmN0aW9uIG9mIGFuIGludGVyY2VwdCBhbmQgYXBwcnByaWF0ZSBjb3ZhcmlhdGVzIChsaWtlIHZpc2liaWxpdHksIGtlbHAsIGV0Yy4pIENvdWxkIGJlIGFuIGludGVyZXN0aW5nIHdheSB0byB0ZXN0IHRoaW5ncyB0aGF0IG5lZWQgdG8gYmUgYWNjb3VudGVkIGZvciBpbiB0aGUgbW9kZWwuIFRoYXQncyByZWFsbHkgd2hhdCBlcXVhdGlvbiA2LjIuNTEgaW4gQlAgaXMgZG9pbmc6IG1ha2luZyBhIG1vcmUgY29tcGxleCBtb2RlbCBvZiB0aGUgZXJyb3Igc3RydWN0dXJlIGFzc29jaWF0ZWQgd2l0aCB0aGUgb2JzZXJ2YXRpb25zLiAKCjMuIEEgZGF0YS1nZW5lcmF0aW9uIG1vZGVsLCB3aGVyZSB0aGUgbGVuZ3RoIGZyZXF1ZW5jeSBhcmUgdGFrZW4gYXMgcGVyZmVjdGx5IG9ic2VydmVkLCBvciBhcmUgdXNlZCB0byBnZW5lcmF0ZSBkcmF3cyBmcm9tIGEgcG9pc3NvbiwgYSBsYSBAS2FybmF1c2thczIwMTEsIGNvbnZlcnRlZCB0byBkZW5zaXRpZXMsIGFuZCB0aGVuIHRoZSByZWdyZXNzaW9uIGlzIGZpdCB0byB0aG9zZSBkZW5zaXRpZXMsIGFuZCB0aGVuIHVzZWQgdG8gcHJlZGljdCB0aGUgb2JzZXJ2ZWQgZGVuc2l0aWVzLiBTZWVtcyBsaWtlIGEgd29yc2UgYW5kIHdvcnNlIGlkZWEsIGVzcGVjaWFsbHkgaWYgeW91J3JlIG5vdCBhcyBpbnRlcmVzdGVkIGluIHByZWRpY3Rpb24gYXMgeW91IGFyZSBpbiBlc3RpbWF0aW9uLgoKIyMjIFBhcmFtZXRlcnMKCkxldCdzIHRoaW5rIGFib3V0IHRoZSBjb3ZhcmlhdGVzIGZpcnN0LiBUaGUgcXVlc3Rpb24gaXMgYmFzaWNhbGx5IGhvdyBkbyB5b3Ugd2FudCB0byBjbHVzdGVyIHRoZSBlcnJvcnMuIAojIyMjIFNpdGVzCgpZb3UgaGF2ZSBzaXRlIHNwZWNpZmljIHBhcmFtZXRlcnMsIGxpa2UgbG9jYXRpb24sIHJlZ2lvbiwgZXRjLiBUaGVzZSBzdGF5IGNvbnN0YW50IGF0IGVhY2ggc2l0ZSBvdmVyIHRpbWUuIFRob3NlIHNob3VsZCBhbG1vc3QgY2VydGFpbmx5IGJlIG1vZGVsZWQgYXMgcmFuZG9tIGVmZmVjdHMsIHdoZXJlIG1heWJlIGVhY2ggc2l0ZSBnZXRzIGFuIGludGVyY2VwdCwgZHJhd24gZnJvbSB0aGUgcmVnaW9uIHRoYXQgaXQncyBpbiwgYW5kIGVhY2ggcmVnaW9uIHRoZW4gZ2V0J3MgYW4gdW5pbmZvcm1hdGl2ZSBwcmlvciwgc2luY2UgdGhlIHJlZ2lvbidzIGFyZW4ndCByZWFsbHkgcmFuZG9tIGVmZmVjdHMsIGJ1dCBjb25zdGFudCBlbml0aWVzIGluIHRoaXMgd29ybGQuCgpOb3cgb25lIHF1ZXN0aW9uIEkgaGF2ZSB0aGVuIGlzIGhvdyBkb2VzIHRoYXQgZml0IGluIGEgcmVncmVzc2lvbiBmcmFtZXdvcmssIGkuZS4gcmVsYXRpdmUgdG8gImNvbnRyb2xsaW5nIiBmb3IgdGhlIHJlZ2lvbiBlZmZlY3QgaW4gdGhlIHJlZ3Jlc3Npb24gaXRzZWxmLiBJIGRvbid0IHRoaW5rIHRoYXQgaXQgbWF0dGVycywgeW91IGp1c3QgbmVlZCB0byBzdG9wIHRoaW5raW5nIGFib3R1IHRoaW5ncyBzbyBsaW5lYXJseS4gWW91J3JlIG9ubHkgZ29hbCBpcyB0byBtb2RlbCB0aGUgdmFyaWF0aW9uIGluIGRlbnNpdHkgYXMgYSBmdW5jdGlvbiBvZiB0aGluZ3MsIGFuZCB0aGlzIGdvZXMgaW4gdGhlcmUsIHRoZSBlZmZlY3Qgb2YgcmVnaW9uIGp1c3QgaXNuJ3QgYSBsaW5lYXIgYWRkaXRpdmUgdGVybSwgYnV0IHJhdGhlciBhZmZlY3RzIHRoZSBzaXRlIHNwZWNpZmljIHRlcm1zCgojIyMgU3BlY2llcwoKWW91IGFsc28gaGF2ZSBhIGJ1bmNoIG9mIHNwZWNpZXMtc3BlY2lmaWMgZWZmZWN0cy4gTm93LCBvbiBvbmUgbGV2ZWwsIHRoZXNlIG1ha2UgbW9yZSBzZW5zZSB0byBtZSBhcyBmaXhlZCBlZmZlY3RzICh0aGUgaWRlYSBpcyB0aGF0IHRoZXkgYXJlbid0IHJlYWxseSByYW5kb20gZHJhd3MgZnJvbSBhIHBvcHVsYXRpb24sIGJ1dCByYXRoZXIgInRydWUiIHZhbHVlcykuIEJ1dCwgd2hlcmUgSSBnZXQgY29uZnVzZWQgdGhlbiBpcyBob3cgdG8gZGVhbCB3aXRoIHRoZXNlIGNvcnJlY3RseSBpbiBhIHBhbmVsIGZyYW1ld29yaywgZ2l2ZW4gdGhhdCB0aGV5IGFyZSByZXBlYXRlZC4gSWYgSSByZW1lbWJlciBteSBHZWxtYW4sIHRoZSB3YXkgdG8gZGVhbCB3aXRoIHRoaXMgaW4gdGhlIHllYXIgdGVybXMgZm9yIGV4YW1wbGUgaXMgYnkgZ2l2aW5nIHRoZW0gYSBoaWVyYXJjaGljaGFsIG5hdHVyZS4gCgpTbywgbWF5YmUgb25lIHdheSB0byB0aGluayBvZiBhbGwgdGhlIGxpZmUgaGlzdG9yeSB0aGluZ3MgaXMgdGhhdCBlYWNoIGxpZmUgaGlzdG9yeSB2YWx1ZSBpcyBhIGRyYXcgZnJvbSBhICJyYW5kb20iIG1vZGVsIHRoYXQgZ2VucmF0ZXMgbGlmZSBoaXN0b3J5IHRyYWl0cy4gU28sIHlvdSBlc3RpbWF0ZSB0aGUgY29lZmZpY2llbnRzIGZvciBsaW5mLCB3aGVyZSBsaW5mIGlzIGEgcmFuZG9tIHZhcmlhYmxlIGRyYXduIGEgZ2xvYmFsIGRpc3RyaWJ1dGlvbi4gCgpBSEEsIGkgdGhpbmsgeW91ciBjb25mdXNpb24gaXMgaW4gZGlmZmVyZW50aWF0aW5nIHRoZSBkYXRhIGZyb20gdGhlIGNvZWZmaWNpZW50cy4gSSB0aGluayB0aGUgInJhbmRvbSBlZmZlY3RzIiB2cyAiZml4ZWQgZWZmZWN0cyIgcXVlc3Rpb24gcmVsYXRlcyB0byBob3cgeW91IHdhbnQgdG8gbW9kZWwgdGhlIGRhdGEgaXRzZWxmLCBhcyBlaXRoZXIgdGhlIGRhdGEsIG9yIGRyYXdzIGZyb20gc29tZSBkaXN0cmlidXRpb24gdGhhdCB5b3UgdGhlbiBlc3RpbWF0ZSBhcyB3ZWxsLiAKCiJJbiBCYXllc2lhbiBoaWVyYXJjaGljYWwgbW9kZWxpbmcsIHJhbmRvbSBlZmZlY3RzIGFyZSB1c2VkIHRvIGRlc2NyaWJlIHZhcmlhdGlvbiB0aGF0IG9jY3VycyBiZXlvbmQgdmFyaWF0aW9uIHRoYXQgYXJpc2VzIGZyb20gc2FtcGxpbmcgYWxvbmUiCgpIb2JicywgTi4gVGhvbXBzb247IEhvb3RlbiwgTWV2aW4gQi4uIEJheWVzaWFuIE1vZGVsczogQSBTdGF0aXN0aWNhbCBQcmltZXIgZm9yIEVjb2xvZ2lzdHMgKFBhZ2UgMTE0KS4gUHJpbmNldG9uIFVuaXZlcnNpdHkgUHJlc3MuIEtpbmRsZSBFZGl0aW9uLiAKCgojIyMgUHJpb3JzCgoKIyMgSmFuIDMgMjAxNwoKIyMjIE5ldyB0aG91Z2h0cyBvbiBtb2RlbCBzdHJ1Y3R1cmUKCk9LLCBhZnRlciBkb2luZyBzb21lIHJlYWRpbmcgSSB0aGluayBJJ20gZ2V0aW5nIGEgYmV0dGVyIGhhbmRsZSBvbiB0aGlzLiBUaGUga2V5IHF1ZXN0aW9uOiBob3cgZG8geW91IHByb3Blcmx5IGFjY291bnQgZm9yIHRoZSBzYW1wbGluZyBuYXR1cmUgb2YgdGhlIE1MUEEgZGF0YQoKClRoZSBwcm9ibGVtIGlzIHlvdSd2ZSBiZWVuIHRoaW5raW5nIGFib3V0IHRoaXMgcmF0aGVyIGNvbmZ1c2VkbHkgYmV0d2VlbiB0aGUgdW5jbGVhciBkaXN0aW5jdGlvbiBiZXR3ZWVuIGhpZXJhcmNoaWNhbCBhbmQgc3RhdGUgc3BhY2UgKHNlZSB5b3VyIGV2ZXJub3JlIGVudHJ5IG9uIHN0YXRlIHNwYWNlIG1vZGVsaW5nKS4gCgpTbyBsZXQncyBzdGFydCBmcm9tIHRoZSBncm91bmQgdXAuIAoKMS4gWW91IG9ic2VydmUgc2FtcGxlcyBvZiBsZW5ndGggZGF0YSwgYmlubmVkIGJ5IHNpemUKMi4gVGhlc2Ugc2FtcGxlIGFycmlzZSBmcm9tIGEgdW5kZXJseWluZyB0cnVlIGxlbmd0aCBzdHJ1Y3R1cmUsIGxldCdzIHNheSBhIFBvaXNzb24sIG1lYW5pbmcgdGhhdCB0aGUgbWVhbiBhbmQgU0QgYXJlIHRoZSBzYW1lLiBTbywgeW91IGZpdCBhIG1vZGVsIHRoYXQgcmVwbGljYXRlcyB0aGlzIHByb2Nlc3MgV1JPTkchISEKICAgICogVGhlIHNhbXBsZXMgYXJlIHRoZSBkYXRhISB0aGV5IGFyZSB0aGUgbWVhbiB2YWx1ZXMgb2YgdGhlIHRydWUgcG9pc3NvbiBkaXN0cmlidXRpb24uIFNvLCBpZiB0aGF0J3MgdGhlIGNhc2UsIG5vbmUgb2YgdGhpcyBtYXR0ZXJzIGhhLCBzaW5jZSB0aGVyZSdzIG5vdGhpbmcgdG8gZXN0aW1hdGUuIAoKCklmIHRoYXQncyB0aGUgY2FzZSwgbWF5YmUgeW91IGdvIGJhY2sgdG8gYW4gZXhwbGljaXQgb2JzZXJ2YXRpb24gbW9kZWwsIHdoZXJlIHRoZSBlcnJvciBpbiB0aGUgbGVuZ3RoIHN0cnVjdHVyZXMvYmlvbWFzcyBhcmUgYSBmdW5jdGlvbiBvZiBjb3ZhcmlhdGVzLiAKCgoKICAgIApgYGB7cn0KCmxpYnJhcnkodGlkeXZlcnNlKQoKaHVoIDwtIHJwb2lzKDEwMDAsMTAwKQoKZGF0YV9mcmFtZShodWggPSBodWgpICU+JSAKICBnZ3Bsb3QoYWVzKGh1aCkpICsgCiAgZ2VvbV9iYXIoKQoKcm11bHRpbm9tKDEwLCBzaXplID0gMTIsIHByb2IgPSBjKDAuMSwwLjIsMC44LC4xKSkKCmBgYAoKICAgIAojIyAxLzQvMTcKCk9LLCB0aGF0IHdhcyBhIGdvb2Qgcm9hZCB0byBoZWFkIGRvd24sIGJ1dCBub3QgYSBncmVhdCBwbGFjZSB0byBzdGFydC4gSXQgc2VlbXMgbGlrZSB0aGVyZSdzIG5vdCByZWFsbHkgYSBodWdlIHVwc2lkZSB0byBiZSBoYWQgZnJvbSB0aGUgY3JhenkgbGVuZ3RoLXVwIG1vZGVsaW5nIHByb2Nlc3MuIEF0IHRoZSBlbmQgb2YgdGhlIGRheSwgdW5sZXNzIHlvdSBpbnRyb2R1Y2UgYSBiaWFzIHRlcm0gb3Igc29tZXRoaW5nIGxpa2UgdGhhdCwgeW91J3JlIGp1c3QgZ29pbmcgdG8gZ2V0IHRoZSBtZWFuIG9mIHRoZSBwcmVkaWN0aW9uIGJhY2suIFNvLCB5b3UgY291bGQgY2VydGFpbmx5IGludHJvZHVjZSBhIGJpdCBtb3JlIHVuY2VydGFpbnR5LCBidXQgbm90IHJlYWxseSBhIHN1YnN0YW50aXZlIGNoYW5nZSBpbiB0aGUgb3V0Y29tZS4gCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmRhdCA8LSByZWFkX2NzdignLi4vZGF0YS9VQ1NCX0ZJU0ggcmF3IHRocnUgMjAxMy5jc3YnKQoKZGF0IDwtICBkYXQgJT4lIAogIG11dGF0ZShzaXplX3JhbmdlID0gaWZlbHNlKGlzLm5hKG1heF90bCAtIG1pbl90bCksIDAsIG1heF90bCAtIG1pbl90bCApKQoKZGF0ICU+JSAKICBnZ3Bsb3QoYWVzKHNpemVfcmFuZ2UpKSArCiAgZ2VvbV9oaXN0b2dyYW0oKSArIAogIHNjYWxlX3lfbG9nMTAoKQoKYGBgCkFsbW9zdCBhbGwgdGhlIG9ic2VydmF0aW9ucyBoYXZlIG5vIHJlYWwgcmFuZ2UgdG8gdGhlbS4gTG9va2luZyBhdCBhIGhpc3RvZ3JhbSBvZiB0aGUgcmFuZ2Ugb2YgdGhlIHNpemVzIHJlcG9ydGVkIChtYXggLSBtaW4pLCB3aGVyZSAwIGNvcnJlc3BvbmRzIHRvIG5vIHJhbmdlIHJlcG9ydGVkLCBhbG1vc3QgYWxsIGFyZSB3aXRoaW4gYSBmZXcgY2VudGltZXRlcnMsIHdoaWNoIHJlYWxseSBpc24ndCBnb2luZyB0byBwbGF5IG91ciBpbiB0aGUgYmlvbWFzcyBhbGwgdGhhdCBtdWNoLiBvbmx5IGByIDEwMCptZWFuKGRhdCRzaXplX3JhbmdlID4gMTApYCUgb2Ygc2FtcGxlcyBoYXZlIHNpemUgcmFuZ2VzIGFib3ZlIDEwIGNlbnRpbWV0ZXJzLiBTbywgdG8gYmUgcmVhbGx5IHJlYWxseSBwcmVjaXNlLCB5b3UgY291bGQgc2ltdWxhdGUgbGVuZ3RoIGZyZXF1ZW5jZXMgZm9yIHRob3NlLCBidXQgcmVhbGx5IGhhcmRseSBzZWVtcyB3b3J0aCB0aGUgZWZmb3J0LiAKClRoZSBiaWdnZXIgcXVlc3Rpb24gdGhlbiBpcyBpZiB5b3Ugd2FudCB0byB0cnkgYW5kIG1vZGVsIGJpYXMgaW4gdGhlIG9ic2VydmF0aW9uczsgZS5nLiBjb3VudHMgb2YgY2VydGFpbiBzcGVjaWVzIHJlYWxseSBzaG91bGQgYmUgaGlnaGVyL2xvd2VyIHVuZGVyIGRpZmZlcmVudCBjb25kaXRpb25zLiBTb21ldGhpbmcgbGlrZSBhICJzdGFuZGFyZGl6ZWQiIHN1cnZleSBpbmRleC4gaS5lLiBtYXliZSBjb3VudHMgc2hvdWxkIGJlIGhpZ2hlciwgdGFraW5nIGludG8gYWNjb3VudCBwb29yIHZpcyBvciB0aGUgbGlrZS4gQmFzaWNhbGx5LCBpdCB3aWxsIGJlIGltcG9ydGFudCBpZiBpdCBpbnRyb2R1Y2VzIGJpYXMsIG9yIHRoZXJlIGlzIHN1YnN0YW50aWFsbHkgbW9yZSBlcnJvciBhcm91bmQgcGFydGljdWxhciBraW5kcyBvZiBzcGVjaWVzLiBCdXQgYmV5b25kIHRoYXQsIG5vdCBsaWtlIHlvdXIgYW5hbHlzaXMgaXMgZnVuZGFtZW50YWxseSBmbGF3ZWQgb3IgYW55dGhpbmcsIGFuZCBpdCdzIHVuY2xlYXIgaG93IG11Y2ggYmVuZWZpdCB5b3UgZ2V0IGZyb20gY29udHJvbGxpbmcgZm9yIHRob3NlIGZhY3RvcnMgYXQgdGhlIGdyb3VuZCBsZXZlbCwgdnMuIGNvbnRyb2xsaW5nIGZvciB0aGVtIGluIHRoZSByZWdyZXNzaW9uIGl0c2VsZiAoaS5lLiBhbGwgZWxzZSBiZWluZyBlcXVhbCB2aXNpYmlsaXR5IGRyaXZlcyBkb3duL3VwIGNvdW50cykuIAoKVGhlcmUncyBzdGlsbCB0aGUgYmlvbWFzcyBpc3N1ZSAoY29udmVydGluZyBsZW5ndGhzIGludG8gYmlvbWFzcykuIFRoZXJlJ3Mgb2J2aW91c2x5IGVycm9yIGluIHRoZXJlLCBidXQgcHJvYmFibHkgbm90IGJpYXMsIHNvIGFnYWluLCB0aGUgaXNzdWUgd291bGQgcmVhbGx5IGJlIGluIGp1c3QgYWRkaW5nIG1vcmUgbm9pc2UuIEl0J3MgaGFyZCB0byBrbm93IGhvdyB5b3UnZCBkZWFsIHdpdGggdGhhdCBzaW5jZSB0aGVyZSdzIG5vdCByZWFsbHkgYSBzaWduYWwgaW4gdGhlIGRhdGEgdG8gdGVsbCB5b3UgYW55dGhpbmcgYWJvdXQgdGhhdCBlcnJvci4gSXQgd291bGQgYmUgbmljZSB0byB3b3JrIHdpdGggSmVuIHRvIGRvIHRoZSB0cmFuc2xhdGlvbiBmcm9tIGxlbmd0aHMgdG8gZGVuc2l0aWVzIHJpZ2h0IHRoZXJlIGluIHRoZSBtb2RlbCwgYnV0IGFnYWluIHRoYXQgc2VlbXMgbGlrZSBhIHNlY29uZCBvcmRlciB0aGluZzogSSBkb24ndCB0aGluayB0aGUgZXhpc3RpbmcgZGVuc2l0aWVzIGFyZSB3cm9uZyBvciBhbnl0aGluZy4gVGhlIGJpZ2dlc3QgdGhpbmcgdGhvdWdoIGlzIHRoYXQgZG9pbmcgdGhlIGRlbnNpdGllcyByYXcgd291bGQgYWxsb3cgeW91IHRvIGFjdHVhbGx5IHRhbGx5IHRoZW0gdXAgYXQgdGhlIGFnZ3JlZ2F0aW9uIGxldmVsIHlvdSB3YW50LCBpbnN0ZWFkIG9mIHRha2luZyBtZWFucy9tZWRpYW5zIGFjcm9zcyBzcGFjZSBhbmQgdGltZSwgd2hpY2ggY291bGQgZGlzZ3Vpc2Ugc29tZSB0cmVuZHMuIExldCdzIHdvcmsgb24gdGhhdCBhY3R1YWxseS4gCgpTbywgSSB0aGluayB5b3UncmUgYmFjayBnbyB0aGUgaW1wb3J0YW50IHRoaW5nIGJlaW5nIGRvaW5nIGEgZ29vZCBqb2Igb2YgZGVhbGluZyB3aXRoIHRoZSBoaWVyYXJjaGljYWwgbmF0dXJlIG9mIHRoZSBkYXRhIHRoZW1zZWx2ZXMuIFNvIGxldCdzIHNwZW5kIHRoZSBuZXh0IGZldyBkYXlzIGZvY3VzaW5nIG9uIHRoYXQuIAoKIyMgRGF0YSBFeHBsb3JhdGlvbgoKTGV0J3MgZ28gYmFjayB0byBzcXVhcmUgb25lIGFuZCB0aGluayBhIGxpdHRsZSBhYm91dCB0aGUgbmF0dXJlIG9mIHRoZSBkYXRhIHRoYXQgeW91J3JlIGRlYWxpbmcgd2l0aCwgYW5kIGV4cGxvcmUgdGhlIHJlbGF0aW9uc2hpcHMgb2YgdGhlIGRhdGEgd2l0aCBkZW5zaXR5IGFuZCBsZW5ndGguIAoKYGBge3IgbG9hZCBkYXRhfQoKCmxlbmd0aF9kYXRhIDwtIHJlYWRfY3N2KCcuLi9kYXRhL1VDU0JfRklTSCByYXcgdGhydSAyMDEzLmNzdicpICU+JSAKICAgIG1hZ3JpdHRyOjpzZXRfY29sbmFtZXMoLix0b2xvd2VyKGNvbG5hbWVzKC4pKSkKCgpjb25kaXRpb25zX2RhdGEgPC0gbGVuZ3RoX2RhdGEgJT4lIAogIGdyb3VwX2J5KHNpdGUsc2lkZSx5ZWFyKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5fdGVtcCA9IG1lYW4odGVtcCwgbmEucm0gPSBUKSwKICAgICAgICAgICAgbWVhbl9rZWxwID0gbWVhbihwY3RjbnB5LCBuYS5ybSA9IFQpLAogICAgICAgICAgICBtZWFuX3ZpcyA9IG1lYW4odmlzLCBuYS5ybSA9IFQpKSAKICAKCmxpZmVfaGlzdG9yeV9kYXRhIDwtIHJlYWRfY3N2KCcuLi9kYXRhL1ZSRyBGaXNoIExpZmUgSGlzdG9yeSBpbiBNUEFfMDRfMDhfMTFfMTIgMTEtTWFyLTIwMTQuY3N2JykgJT4lCiAgcmVuYW1lKGNsYXNzY29kZSA9IHBpc2NvX2NsYXNzY29kZSkgJT4lIAogIG1hZ3JpdHRyOjpzZXRfY29sbmFtZXMoLix0b2xvd2VyKGNvbG5hbWVzKC4pKSkKCnNpdGVfZGF0YSA8LSByZWFkX2NzdignLi4vZGF0YS9GaW5hbF9TaXRlX1RhYmxlX1VDU0IuY3N2JykgJT4lCiAgICBtYWdyaXR0cjo6c2V0X2NvbG5hbWVzKC4sdG9sb3dlcihjb2xuYW1lcyguKSkpCgoKbGVuZ3RoX2RhdGEgPC0gbGVuZ3RoX2RhdGEgJT4lIAogIGxlZnRfam9pbihsaWZlX2hpc3RvcnlfZGF0YSwgYnkgPSAnY2xhc3Njb2RlJykgJT4lIAogIGxlZnRfam9pbihzaXRlX2RhdGEsIGJ5ID0gYygnc2l0ZScsJ3NpZGUnKSkKCmBgYAoKIyMgQ29udmVydGluZyBsZW5ndGggdG8gYmlvbWFzcy9kZW5zaXR5CgpPbmUgdGhpbmcgSSdkIGxpa2UgdG8gYmUgYWJsZSB0byBkbyBpcyBtb3ZlIGRpcmVjdGx5IGZyb20gdGhlIGxlbmd0aHMgdG8gdGhlIGRlbnNpdHkgYXQgYW55IGFnZ3JlZ2F0aW9uIHRoYXQgSSdtIGludGVyZXN0ZWQgaW4gYnkgYWN0dWFsbHkgdGFsbHlpbmcgdGhlIGxlbmd0aCBzdHJ1Y3R1cmUuIEFzIGl0IHN0YW5kcyByaWdodCBub3csIHlvdSBuZWVkIHRvIHRha2UgbWVhbnMvbWVkaWFucyB0byBhZ2dyZWdhdGUgZGVuc2l0aWVzIG92ZXIgdGltZSwgd2hpY2ggSSBkb24ndCByZWFsbHkgbGlrZQoKTGV0J3MgdGFrZSBhIGxvb2sgYXQgdGhlIGFjdHVhbCBkZW5zaXR5IGRhdGEgdGhhdCBKZW4gcHJvdmlkZXMKCmBgYHtyIGRlbnNpdHkgZGF0YX0KCmRlbnNpdHlfZGF0YSA8LSByZWFkX2NzdignLi4vZGF0YS9jaV9yZXNlcnZlX2RhdGFfZmluYWwzIHR4dC5jc3YnKSAlPiUKICBtYWdyaXR0cjo6c2V0X2NvbG5hbWVzKC4sdG9sb3dlcihjb2xuYW1lcyguKSkpICU+JSAKICBnYXRoZXIoJ2NvbmNhdC5uYW1lJywndmFsdWUnLCBncmVwKCdfJyxjb2xuYW1lcyguKSksY29udmVydCA9IFQpICU+JQogIG11dGF0ZShkYXRhLnR5cGUgPSBnc3ViKCdcXF8uKicsICcnLCBjb25jYXQubmFtZSksCiAgICAgICAgIGNsYXNzY29kZSA9IGdzdWIoJy4qXFxfJywnJyxjb25jYXQubmFtZSkpICU+JQogIG11dGF0ZSh2YWx1ZSA9IGFzLm51bWVyaWModmFsdWUpKSAlPiUKICBzcHJlYWQoZGF0YS50eXBlLHZhbHVlKSAlPiUKICByZW5hbWUoc2l0ZV9zaWRlID0gc2l0ZS5zaWRlKQoKZGVuc2l0eV9leGFtcGxlIDwtIGRlbnNpdHlfZGF0YSAlPiUgCiAgZmlsdGVyKGlzLm5hKGJpb21hc3MpID09IEYgJiBiaW9tYXNzID4wKSAlPiUgCiAgc2FtcGxlX24oMSkKCmRlbnNpdHlfZXhhbXBsZQoKYGBgCkxldCdzIHRha2UgYSBsb29rIGFuZCBzZWUgaWYgeW91IGNhbiByZXBsaWNhdGUgdGhpcyBkZW5zaXR5IGV4YW1wbGUuIAoKCgoKCmBgYHtyfQoKCmxlbmd0aF90b193ZWlnaHQgPC0KICBmdW5jdGlvbihtZWFuX2xlbmd0aCwKICBtaW5fbGVuZ3RoLAogIG1heF9sZW5ndGgsCiAgY291bnQsCiAgd2VpZ2h0X2EsCiAgd2VpZ2h0X2IsCiAgbGVuZ3RoX3VuaXRzID0gJ2NtJywKICB3ZWlnaHRfdW5pdHMgPSAnZycsCiAgbGVuZ3RoX2Zvcl93ZWlnaHRfdW5pdHMgPSAnbW0nLAogIGxlbmd0aF90eXBlX2Zvcl93ZWlnaHQsCiAgdGxfc2xfYSwKICB0bF9zbF9iLAogIHRsX3NsX3R5cGUsCiAgdGxfc2xfZm9ybXVsYSkgewogICMKICAjIGdlbmVyYXRlX2xlbmd0aHMgPC0gZnVuY3Rpb24oY291bnQsbWVhbl9sZW5ndGgsIG1pbl9sZW5ndGgsIG1heF9sZW5ndGgpewogIAogIGlmIChpcy5uYShjb3VudCkgfCBjb3VudCA9PSAwKXsKICAgIAogICAgb3V0d2VpZ2h0IDwtICAwCiAgfSAgZWxzZSB7CiAgICAKICBpZiAoaXMubmEobWluX2xlbmd0aCkgfAogIGlzLm5hKG1heF9sZW5ndGgpKSB7CiAgI2dlbmVyYXRlIGRpc3RyaWJ1dGlvbiBvZiBsZW5ndGhzCiAgCiAgbGVuZ3RocyA8LSAgcmVwKG1lYW5fbGVuZ3RoLCBjb3VudCkKICAKICB9IGVsc2V7CiAgIyBsZW5ndGhzIDwtICBwbWF4KG1pbl9sZW5ndGgscG1pbihtYXhfbGVuZ3RoLHJwb2lzKGNvdW50LCBsYW1iZGEgPSBtZWFuX2xlbmd0aCkpKQogIGxlbmd0aHMgPC0gcnVuaWYoY291bnQsIG1pbiA9IG1pbl9sZW5ndGgsIG1heCA9IG1heF9sZW5ndGgpCiAgfQoKICBpZiAobGVuZ3RoX3R5cGVfZm9yX3dlaWdodCA9PSAnU0wnKSB7CiAgaWYgKHRsX3NsX3R5cGUgID09ICdUWVBJQ0FMJykgewogIHdlaWdodF9sZW5ndGhzIDwtICBsZW5ndGhzICogdGxfc2xfYSArIHRsX3NsX2IKICB9IGVsc2V7CiAgd2VpZ2h0X2xlbmd0aHMgPC0gKGxlbmd0aHMgLSB0bF9zbF9iKSAvIHRsX3NsX2EKICAKICB9CiAgCiAgfSBlbHNlIHsKICB3ZWlnaHRfbGVuZ3RocyA8LSAgbGVuZ3RocwogIH0KICAKICBpZiAobGVuZ3RoX3VuaXRzID09ICdjbScgJiBsZW5ndGhfZm9yX3dlaWdodF91bml0cyA9PSAnbW0nKSB7CiAgd2VpZ2h0X2xlbmd0aHMgPC0gd2VpZ2h0X2xlbmd0aHMgKiAxMAogIH0KICAKICB3ZWlnaHQgPC0gIHdlaWdodF9hICogd2VpZ2h0X2xlbmd0aHMgXiB3ZWlnaHRfYgogIAogIGlmICh3ZWlnaHRfdW5pdHMgPT0gJ2tnJykgewogIHdlaWdodCA8LSB3ZWlnaHQgKiAxMDAwCiAgfQogIG91dHdlaWdodCA9IHN1bSh3ZWlnaHQpCiAgfQogICAgcmV0dXJuKG91dHdlaWdodCkKICB9ICNjbG9zZSBmdW5jdGlvbgogIApsZW5ndGhfZXhhbXBsZSA8LSBsZW5ndGhfZGF0YSAlPiUgCiAgZmlsdGVyKGNsYXNzY29kZSA9PSB0b3VwcGVyKGRlbnNpdHlfZXhhbXBsZSRjbGFzc2NvZGUpCiwgc2l0ZSA9PSBkZW5zaXR5X2V4YW1wbGUkc2l0ZSwgCiAgICAgICAgIHNpZGUgPT0gZGVuc2l0eV9leGFtcGxlJHNpZGUsIHllYXIgPT0gZGVuc2l0eV9leGFtcGxlJHllYXIpIAoKbGVuZ3RoX2V4YW1wbGUgPC0gICBsZW5ndGhfZGF0YSAlPiUgCiAgZmlsdGVyKGlzLm5hKGNvbW1vbm5hbWUpID09IEYpICU+JSAKICBtdXRhdGUoYmlvbWFzc19nID0gcG1hcF9kYmwobGlzdChtZWFuX2xlbmd0aCA9IGZpc2hfdGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluX2xlbmd0aCA9IG1pbl90bCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhfbGVuZ3RoID0gbWF4X3RsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50ID0gY291bnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2VpZ2h0X2EgPSB3bF9hLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdlaWdodF9iID0gd2xfYiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGhfdHlwZV9mb3Jfd2VpZ2h0ID0gd2xfaW5wdXRfbGVuZ3RoLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aF9mb3Jfd2VpZ2h0X3VuaXRzID0gd2xfbF91bml0cywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0bF9zbF9hID0gbGMuYS5fZm9yX3dsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRsX3NsX2IgPSBsYy5iLl9mb3Jfd2wsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGxfc2xfdHlwZSA9IGxjX3R5cGVfZm9yX3dsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRsX3NsX2Zvcm11bGEgPSBsbF9lcXVhdGlvbl9mb3Jfd2wpLCBsZW5ndGhfdG9fd2VpZ2h0KSkKCmxlbmd0aF9leGFtcGxlICU+JSAKICBzZWxlY3QoYmlvbWFzc19nKQoKYmlvbWFzc19kYXRhIDwtIGxlbmd0aF9leGFtcGxlICU+JSAKICBncm91cF9ieShjbGFzc2NvZGUsIHNpdGUsIHNpZGUsIHllYXIsIHRyYW5zZWN0KSAlPiUgCiAgc3VtbWFyaXNlKHRvdGFsX2Jpb21hc3NfZyA9IHN1bShiaW9tYXNzX2cpKSAKYGBgCkZpcnN0LCBuZWVkIHRvIGFkZCBiYWNrIGluIHplcm9zLiBZb3UgbmVlZCBhIGZ1bmN0aW9uIHRoYXQgZ29lcyB0aHJvdWdoIHRyaXAgYnkgdHJpcCwgYW5kIGFkZHMgaW4gemVyb3MgZm9yIGFsbCBzcGVjaWVzIHNlZW4gYXQgdGhhdCBzaXRlIGF0IHNvbWUgcG9pbnQgYnV0IG5vdCBvbiB0aGF0IHRyaXAuIAoKCmBgYHtyfQoKc3BlY2llc19zaWdodGluZ3MgPC0gbGVuZ3RoX2RhdGEgJT4lIAogIGdyb3VwX2J5KHNpdGUpICU+JSAKICBzdW1tYXJpc2Uoc3BlY2llc19zZWVuID0gbGlzdCh1bmlxdWUoY2xhc3Njb2RlKSkpCgoKYmlvbWFzc19kYXRhIDwtIGJpb21hc3NfZGF0YSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBzZWxlY3Qoc2l0ZSxzaWRlLHllYXIsIHRyYW5zZWN0KSAlPiUgCiAgdW5pcXVlKCkgJT4lICB7CiAgcG1hcCgKICAgIGxpc3QoCiAgICAgIHRoaXNfc2l0ZSA9IC4kc2l0ZSwKICAgICAgdGhpc19zaWRlID0gLiRzaWRlLAogICAgICB0aGlzX3llYXIgPSAuJHllYXIsCiAgICAgIHRoaXNfdHJhbnNlY3QgPSAuJHRyYW5zZWN0CiAgICApLAogICAgYWRkX21pc3NpbmdfZmlzaCwKICAgIG9ic2VydmF0aW9ucyA9IGJpb21hc3NfZGF0YSwKICAgIHNwZWNpZXNfc2lnaHRpbmdzID0gc3BlY2llc19zaWdodGluZ3MKICApCn0gJT4lIAogIGJpbmRfcm93cygpCgptYW5fZGVuc2l0eV9kYXRhIDwtIGJpb21hc3NfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoY2xhc3Njb2RlLCBzaXRlLCBzaWRlLHllYXIpICU+JSAKICBzdW1tYXJpc2UobWVhbl9iaW9tYXNzX2cgPSBtZWFuKHRvdGFsX2Jpb21hc3NfZywgbmEucm0gPSBUKSkgJT4lIAogIG11dGF0ZSgKICAgICAgICAgICAgYmlvbWFzc19nX3Blcl9tMiA9IG1lYW5fYmlvbWFzc19nIC8gKDMwKjQpLAogICAgICAgICAgICBiaW9tYXNzX2dfcGVyX2hlY3RhcmUgPSBiaW9tYXNzX2dfcGVyX20yICogMTAwMDAsCiAgICAgICAgICAgIGJpb21hc3NfdG9uX3Blcl9oZWN0YXJlID0gYmlvbWFzc19nX3Blcl9oZWN0YXJlICogMWUtNikKCgpgYGAKCgpgYGB7cn0KCgpgYGAKCgoKT0shIFlvdSd2ZSBnb3QgaGFuZCBjYWxjdWxhdGVkIGRlbnNpdGllcyBub3csIGxldCdzIGNvbXBhcmUgdGhlbSB0byBqZW5zCgpgYGB7cn0KCmRlbnNpdHlfY29tcF9wbG90IDwtIGRlbnNpdHlfZGF0YSAlPiUgCiAgc2VsZWN0KGNsYXNzY29kZSwgc2l0ZSwgc2lkZSwgeWVhciwgYmlvbWFzcykgJT4lIAogIG11dGF0ZShjbGFzc2NvZGUgPSB0b3VwcGVyKGNsYXNzY29kZSkpICU+JSAKICBsZWZ0X2pvaW4obWFuX2RlbnNpdHlfZGF0YSwgYnkgPSBjKCdjbGFzc2NvZGUnLCdzaXRlJywnc2lkZScsJ3llYXInKSkgJT4lIAogIGxlZnRfam9pbihsaWZlX2hpc3RvcnlfZGF0YSwgYnkgPSAnY2xhc3Njb2RlJykgJT4lIAogIGdncGxvdChhZXMoYmlvbWFzcyxiaW9tYXNzX3Rvbl9wZXJfaGVjdGFyZSwgY29sb3IgPSBjb21tb25uYW1lKSkgKyAKICAgICAgICAgICAgIGdlb21fYWJsaW5lKGFlcyhpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpLCBsaW5ldHlwZT0gMikgKwoKICAgICAgICAgICBnZW9tX3BvaW50KCkgKyAKICBzY2FsZV9jb2xvcl9kaXNjcmV0ZShndWlkZSA9IEYpICsgCiAgbGFicyggeSA9ICdCaW9tYXNzICh0b25zIHBlciBoZWN0YXJlKSAtIGNhbGN1bGF0ZWQgZnJvbSBsZW5ndGhzIGFuZCB3ZWlnaHRzJywgeCA9ICdCaW9tYXNzICh0b25zIHBlciBoZWN0YXJlKSAtIGZyb20gY2lfcmVzZXJ2ZV9kYXRhX2ZpbmFsMyB0eHQuY3N2JywgCiAgY2FwdGlvbiA9ICdSZXNvbHV0aW9uIGlzIGF0IHNwZWNpZXMteWVhci1zaXRlLXNpZGUnKQoKZGVuc2l0eV9jb21wX3Bsb3QKZ2dzYXZlKGRlbnNpdHlfY29tcF9wbG90LCBmaWxlID0gJ2RlbnNpdHkgY29tcGFyaXNvbiBwbG90LnBkZicsZGV2ID0gY2Fpcm9fcGRmKQojIHBsb3RseTo6Z2dwbG90bHkoZGVuc2l0eV9jb21wX3Bsb3QpCgpgYGAKCgpOb3QgQmFkLiBJdCdzIGEgZ29vZCBzdGFydGluZyBwb2ludCwgYW5kIG1ha2VzIG1lIGNvbmZpZGVudCB0aGF0IEknbSB1bmRlcnN0YW5kaW5nIHRoaW5ncyByaWdodC4gWW91J2xsIG5lZWQgdG8gdGFsayB3aXRoIEplbiB0byBmaWd1cmUgb3V0IHdoeSB0aGlzIGlzbid0IDE6MS4gVGhpcyBhbHNvIGxldCdzIHlvdSBjb21wYXJlIG91dGNvbWVzIHVuZGVyIHRoZSB0d28gc291cmNlcy4gCiMjIEV4cGxvcmluZyByZWxhdGlvbnNoaXBzCgpMZXQncyBkaWcgaW50byB0aGluZ3MgYSBiaXQgaGVyZSBhbmQganVzdCBsb29rIGF0IHRyZW5kcyBpbiB0aGUgKHRvIHN0YXJ0IHdpdGgpIHR3byB2ZXJzaW9ucyBvZiB0aGUgZGF0YWJhc2UKCmBgYHtyfQoKbWFuX2RlbnNpdHlfZGF0YSA8LSBtYW5fZGVuc2l0eV9kYXRhICU+JSAKICBsZWZ0X2pvaW4obGlmZV9oaXN0b3J5X2RhdGEsIGJ5ID0gJ2NsYXNzY29kZScpICU+JSAKICBsZWZ0X2pvaW4oc2l0ZV9kYXRhLCBieSA9IGMoJ3NpdGUnLCdzaWRlJykpCgptYW5fZGVuc2l0eV9kYXRhICU+JSAKICBmaWx0ZXIoaXMubmEodGFyZ2V0ZWQpID09IEYpICU+JSAKICBncm91cF9ieShyZWdpb24sIHllYXIsIHRhcmdldGVkKSAlPiUgCiAgc3VtbWFyaXNlKG1lZGlhbl9iaW9tYXNzID0gbWVhbihiaW9tYXNzX3Rvbl9wZXJfaGVjdGFyZSwgbmEucm0gPSBUKSkgJT4lIAogIGdncGxvdChhZXMoeWVhcixtZWRpYW5fYmlvbWFzcywgY29sb3IgPSB0YXJnZXRlZCkpICsgCiAgZ2VvbV9saW5lKCkgKyAKICBmYWNldF93cmFwKH5yZWdpb24pCgoKYGBgCgpOb3cgc2FtZSB0aGluZywgYnV0IHdpdGggSmVuJ3MgZGF0YQoKYGBge3J9CmRlbnNpdHlfZGF0YSAlPiUgCiAgbXV0YXRlKGNsYXNzY29kZSA9IHRvdXBwZXIoY2xhc3Njb2RlKSkgJT4lIAogICAgbGVmdF9qb2luKGxpZmVfaGlzdG9yeV9kYXRhLCBieSA9ICdjbGFzc2NvZGUnKSAlPiUgCiAgZmlsdGVyKGlzLm5hKHRhcmdldGVkKSA9PSBGKSAlPiUgCiAgZ3JvdXBfYnkocmVnaW9uLCB5ZWFyLCB0YXJnZXRlZCkgJT4lIAogIHN1bW1hcmlzZShtZWFuX2Jpb21hc3MgPSBtZWFuKGJpb21hc3MsIG5hLnJtID0gVCkpICU+JSAKICBnZ3Bsb3QoYWVzKHllYXIsbWVhbl9iaW9tYXNzLCBjb2xvciA9IHRhcmdldGVkKSkgKyAKICBnZW9tX2xpbmUoKSArIAogIGZhY2V0X3dyYXAofnJlZ2lvbikKYGBgCgoKCkFuZCBqdXN0IGEgcmVhbGx5IHF1aWNrIHJlZ3Jlc3Npb24gZXhwbG9yYXRpb24KCmBgYHtyfQoKCgpyZWdfZGF0YSA8LSBkZW5zaXR5X2RhdGEgJT4lIAogIG11dGF0ZShjbGFzc2NvZGUgPSB0b3VwcGVyKGNsYXNzY29kZSkpICU+JSAKICAgIGxlZnRfam9pbihsaWZlX2hpc3RvcnlfZGF0YSwgYnkgPSAnY2xhc3Njb2RlJykgJT4lIAogICAgICBsZWZ0X2pvaW4oY29uZGl0aW9uc19kYXRhLCBieSA9IGMoJ3NpdGUnLCdzaWRlJywneWVhcicpKSAlPiUgCiAgZmlsdGVyKGlzLm5hKHRhcmdldGVkKSA9PSBGKSAlPiUgCiAgZmlsdGVyKGJpb21hc3MgPiAwKSAlPiUgCiAgbXV0YXRlKGxvZ19iaW9tYXNzID0gbG9nKGJpb21hc3MpLAogICAgICAgICBtbHBhX2luX2VmZmVjdCA9IGFzLm51bWVyaWMoeWVhciA+IDIwMDMpLAogICAgICAgICBmaXNoZWQgPSBhcy5udW1lcmljKHRhcmdldGVkID09ICdUYXJnZXRlZCcpLAogICAgICAgICBkaWQgPSBhcy5udW1lcmljKGZpc2hlZCAqIHllYXIgKiBtbHBhX2luX2VmZmVjdCkpCgpyZWdfZm1sYSA8LSBhcy5mb3JtdWxhKCdsb2dfYmlvbWFzcyB+ICBhcy5mYWN0b3IoeWVhcikgKyBmaXNoZWQgKyAgYXMuZmFjdG9yKGRpZCkgKyB0cm9waGljZ3JvdXAgKyB2YmdmLmxpbmYgKwogICAgICAgICAgICAgICAgICAgICAgIG1lYW5fdGVtcCcpCgoKYmFzaWNfcmVnIDwtIGxtKHJlZ19mbWxhLCBkYXRhID0gcmVnX2RhdGEpCgojIHN0YW5fcmVnIDwtIHJzdGFuYXJtOjpzdGFuX2dsbShyZWdfZm1sYSwgZGF0YSA9IHJlZ19kYXRhKQoKc3VtbWFyeShiYXNpY19yZWcpCgpicm9vbTo6dGlkeShiYXNpY19yZWcpCgogIGJhc2ljX3JlZyAlPiUKICAgIGJyb29tOjp0aWR5KCkgJT4lCiAgICBmaWx0ZXIoc3RyX2RldGVjdCh0ZXJtLCdkaWQnKSkgJT4lCiAgICBtdXRhdGUoeWVhciA9IGFzLm51bWVyaWMoc3RyX3JlcGxhY2UodGVybSwnYXMuZmFjdG9yXFwoZGlkXFwpJywnJykpICklPiUKICAgIGdncGxvdCgpICsKICAgIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAwKSkgKyAKICAgIGdlb21fcG9pbnRyYW5nZShhZXMoeCA9IHllYXIsIHkgPSBlc3RpbWF0ZSwgeW1pbiA9IGVzdGltYXRlIC0gMS45NipzdGQuZXJyb3IsIHltYXggPSBlc3RpbWF0ZSArIDEuOTYgKiBzdGQuZXJyb3IpKSArCiAgICBnZW9tX3Ntb290aChhZXMoeCA9IHllYXIsIHkgPSBlc3RpbWF0ZSksIG1ldGhvZCA9ICdsbScpCgogIAogICAgIyBzdGFuX3JlZyAlPiUKICAgICMgYnJvb206OnRpZHkoKSAlPiUKICAgICMgZmlsdGVyKHN0cl9kZXRlY3QodGVybSwnZGlkJykpICU+JQogICAgIyBtdXRhdGUoeWVhciA9IGFzLm51bWVyaWMoc3RyX3JlcGxhY2UodGVybSwnYXMuZmFjdG9yXFwoZGlkXFwpJywnJykpICklPiUKICAgICMgZ2dwbG90KCkgKwogICAgIyBnZW9tX3BvaW50cmFuZ2UoYWVzKHggPSB5ZWFyLCB5ID0gZXN0aW1hdGUsIHltaW4gPSBlc3RpbWF0ZSAtIDEuOTYqc3RkLmVycm9yLCB5bWF4ID0gZXN0aW1hdGUgKyAxLjk2ICogc3RkLmVycm9yKSkgKyAKICAgICMgICAgICAgZ2VvbV9zbW9vdGgoYWVzKHggPSB5ZWFyLCB5ID0gZXN0aW1hdGUpLCBtZXRob2QgPSAnbG0nKQoKCgpgYGAKCgpgYGB7cn0KCnJlZ19kYXRhIDwtIG1hbl9kZW5zaXR5X2RhdGEgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgZmlsdGVyKGlzLm5hKHRhcmdldGVkKSA9PSBGKSAlPiUgCiAgZmlsdGVyKGJpb21hc3NfdG9uX3Blcl9oZWN0YXJlID4gMCkgJT4lIAogIG11dGF0ZShsb2dfYmlvbWFzcyA9IGxvZyhiaW9tYXNzX3Rvbl9wZXJfaGVjdGFyZSksCiAgICAgICAgIG1scGFfaW5fZWZmZWN0ID0gYXMubnVtZXJpYyh5ZWFyID4gMjAwMyksCiAgICAgICAgIGZpc2hlZCA9IGFzLm51bWVyaWModGFyZ2V0ZWQgPT0gJ1RhcmdldGVkJyksCiAgICAgICAgIGRpZCA9IGFzLm51bWVyaWMoZmlzaGVkICogeWVhciAqIG1scGFfaW5fZWZmZWN0KSkKCnJlZ19mbWxhIDwtIGFzLmZvcm11bGEoJ2xvZ19iaW9tYXNzIH4gIGFzLmZhY3Rvcih5ZWFyKSArIGZpc2hlZCArICBhcy5mYWN0b3IoZGlkKSArIHRyb3BoaWNncm91cCArIHZiZ2YubGluZicpCgoKYmFzaWNfcmVnIDwtIGxtKHJlZ19mbWxhLCBkYXRhID0gcmVnX2RhdGEpCgojIHN0YW5fcmVnIDwtIHJzdGFuYXJtOjpzdGFuX2dsbShyZWdfZm1sYSwgZGF0YSA9IHJlZ19kYXRhKQoKIyBzdW1tYXJ5KGJhc2ljX3JlZykKIyAKIyBicm9vbTo6dGlkeShiYXNpY19yZWcpCgogIGJhc2ljX3JlZyAlPiUKICAgIGJyb29tOjp0aWR5KCkgJT4lCiAgICBmaWx0ZXIoc3RyX2RldGVjdCh0ZXJtLCdkaWQnKSkgJT4lCiAgICBtdXRhdGUoeWVhciA9IGFzLm51bWVyaWMoc3RyX3JlcGxhY2UodGVybSwnYXMuZmFjdG9yXFwoZGlkXFwpJywnJykpICklPiUKICAgIGdncGxvdCgpICsKICAgIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAwKSkgKyAKICAgIGdlb21fcG9pbnRyYW5nZShhZXMoeCA9IHllYXIsIHkgPSBlc3RpbWF0ZSwgeW1pbiA9IGVzdGltYXRlIC0gMS45NipzdGQuZXJyb3IsIHltYXggPSBlc3RpbWF0ZSArIDEuOTYgKiBzdGQuZXJyb3IpKSArCiAgICBnZW9tX3Ntb290aChhZXMoeCA9IHllYXIsIHkgPSBlc3RpbWF0ZSksIG1ldGhvZCA9ICdsbScpCgogIAogICAgIyBzdGFuX3JlZyAlPiUKICAgICMgYnJvb206OnRpZHkoKSAlPiUKICAgICMgZmlsdGVyKHN0cl9kZXRlY3QodGVybSwnZGlkJykpICU+JQogICAgIyBtdXRhdGUoeWVhciA9IGFzLm51bWVyaWMoc3RyX3JlcGxhY2UodGVybSwnYXMuZmFjdG9yXFwoZGlkXFwpJywnJykpICklPiUKICAgICMgZ2dwbG90KCkgKwogICAgIyBnZW9tX3BvaW50cmFuZ2UoYWVzKHggPSB5ZWFyLCB5ID0gZXN0aW1hdGUsIHltaW4gPSBlc3RpbWF0ZSAtIDEuOTYqc3RkLmVycm9yLCB5bWF4ID0gZXN0aW1hdGUgKyAxLjk2ICogc3RkLmVycm9yKSkgKyAKICAgICMgICAgICAgZ2VvbV9zbW9vdGgoYWVzKHggPSB5ZWFyLCB5ID0gZXN0aW1hdGUpLCBtZXRob2QgPSAnbG0nKQoKCgpgYGAKCgpXZWxsIHRoYXQncyBub3QgZW5jb3VyYWdpbmc6IHRoaXMgc3VnZ2VzdHMgdGhhdCB0aGUgZGVuc2l0eSBjYWxjdWxhdGlvbiByZWFsbHkgZG9lcyBtYXR0ZXIgaGVyZS4gWW91J2xsIGdvIHdpdGggSmVuJ3MgZGF0YSBmb3Igbm93LCBidXQgYmlnIHJlZCBmbGFnIG9mIHNvbWV0aGluZyB0aGF0IG5lZWRzIGZpeGluZyBoZXJlLiAKCgoKIyMgQXJlIHVuZmlzaGVkIGFuZCBmaXNoZWQgdmFsaWQgY29udHJvbHM/CgpUaGVyZSBhcmUgYSBmZXcgd2F5cyB5b3UgY291bGQgdGhpbmsgYWJvdXQgdGVzdGluZyBmb3IgdGhpcy4gCgoxLiBEb2VzIHRoZSBNTFBBIGNvbWUgb3V0IGFzIGEgY2F1c2FsIGZhY3RvciBvbiB0aGUgdW5maXNoZWQgc3BlY2llcz8KCjIuIERvIGZpc2hlZCBzcGVpY2VzL3VuZmlzaGVkIHNwZWNpZXMgY2F1c2UgZWFjaCBvdGhlciAoZG8gbGFncyBvZiBmaXNoZWQgc3BlY2llcyBwcmVkaWN0IHVuZmlzaGVkIGFuZCB2aWNlIHZlcnNhKQoKCgpgYGB7cn0KcmVnX2RhdGEgPC0gZGVuc2l0eV9kYXRhICU+JSAKICBtdXRhdGUoY2xhc3Njb2RlID0gdG91cHBlcihjbGFzc2NvZGUpKSAlPiUgCiAgICBsZWZ0X2pvaW4obGlmZV9oaXN0b3J5X2RhdGEsIGJ5ID0gJ2NsYXNzY29kZScpICU+JSAKICBsZWZ0X2pvaW4oY29uZGl0aW9uc19kYXRhLCBieSA9IGMoJ3NpdGUnLCdzaWRlJywneWVhcicpKSAlPiUgCiAgZmlsdGVyKGlzLm5hKHRhcmdldGVkKSA9PSBGKSAlPiUgCiAgZmlsdGVyKGJpb21hc3MgPiAwKSAlPiUgCiAgbXV0YXRlKGxvZ19iaW9tYXNzID0gbG9nKGJpb21hc3MpLAogICAgICAgICBtbHBhX2luX2VmZmVjdCA9IGFzLm51bWVyaWMoeWVhciA+IDIwMDMpLAogICAgICAgICB1bmZpc2hlZCA9IGFzLm51bWVyaWModGFyZ2V0ZWQgIT0gJ1RhcmdldGVkJyksCiAgICAgICAgIGRpZCA9IGFzLm51bWVyaWModW5maXNoZWQgKiB5ZWFyICogbWxwYV9pbl9lZmZlY3QpKQoKcmVnX2ZtbGEgPC0gYXMuZm9ybXVsYSgnbG9nX2Jpb21hc3MgfiAgYXMuZmFjdG9yKHllYXIpICsgbWVhbl90ZW1wK3VuZmlzaGVkICsgIGFzLmZhY3RvcihkaWQpICsgdHJvcGhpY2dyb3VwICsgdmJnZi5saW5mJykKCgpiYXNpY19yZWcgPC0gbG0ocmVnX2ZtbGEsIGRhdGEgPSByZWdfZGF0YSkKCiMgc3Rhbl9yZWcgPC0gcnN0YW5hcm06OnN0YW5fZ2xtKHJlZ19mbWxhLCBkYXRhID0gcmVnX2RhdGEpCgpzdW1tYXJ5KGJhc2ljX3JlZykKCmJyb29tOjp0aWR5KGJhc2ljX3JlZykKCiAgYmFzaWNfcmVnICU+JQogICAgYnJvb206OnRpZHkoKSAlPiUKICAgIGZpbHRlcihzdHJfZGV0ZWN0KHRlcm0sJ2RpZCcpKSAlPiUKICAgIG11dGF0ZSh5ZWFyID0gYXMubnVtZXJpYyhzdHJfcmVwbGFjZSh0ZXJtLCdhcy5mYWN0b3JcXChkaWRcXCknLCcnKSkgKSU+JQogICAgZ2dwbG90KCkgKwogICAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDApKSArIAogICAgZ2VvbV9wb2ludHJhbmdlKGFlcyh4ID0geWVhciwgeSA9IGVzdGltYXRlLCB5bWluID0gZXN0aW1hdGUgLSAxLjk2KnN0ZC5lcnJvciwgeW1heCA9IGVzdGltYXRlICsgMS45NiAqIHN0ZC5lcnJvcikpICsKICAgIGdlb21fc21vb3RoKGFlcyh4ID0geWVhciwgeSA9IGVzdGltYXRlKSwgbWV0aG9kID0gJ2xtJykKCgpgYGAKCkkgZG9uJ3QgdGhpbmsgdGhhdCB0aGF0J3MgYSB2YWxpZCBjb21wYXJpc29uLCBzaW5jZSB5b3UgYXQgbGVhc3QgYXNzdW1lIHRoYXQgdGhlIGZpc2hlZCBhcmVuJ3QgYSBjb250cm9sLiBZb3UgY291bGQgYWxzbyBqdXN0IGRvIGEgY2hhbmdlcG9pbnQgYW5hbHlzaXM/CgpBbHRlcm5hdGl2ZWx5LCBsZXQncyB0aGluayBhYm91dCB0aGlzIG1lY2hhbmlzdGljYWxseS4gSWYgeW91IGJlbGlldmUgdGhhdCB0aGUgInRhcmdldGVkIiBjbGFzc2lmaWNhdGlvbiBpcyByZWFsLCB0aGVuIGJ5IGRlZmluaXRpb24gdGhlIE1QQSBoYXMgbm8gZGlyZWN0IGVmZmVjdCBvbiB0aGUgZmlzaGVkIHNwZWNpZXMuIFRoZSByZWFsIHF1ZXN0aW9uIHRoZW4gaXMgd2hldGhlciB0aGVyZSBhcmUgdHJvcGhpYyBpbnRlcmFjdGlvbnMgdGhhdCBjYXVzZSBhIHByb2JsZW0uIFNvLCB3aHkgbm90IHJ1biBhIHJlZ3Jlc3Npb24gb2YgdW5maXNoZWQgZGVuc2l0aWVzIGFzIGEgZnVuY3Rpb24gb2YgdGFyZ2V0ZWQgYWJ1bmRhbmNlLCBjb250cm9sbGluZyBmb3Igb3RoZXIgY3JhcD8KCmBgYHtyLCBpbmNsdWRlPUYsIGV2YWw9Rn0KCnRyb3BoaWNfZGF0YSA8LSBkZW5zaXR5X2RhdGEgJT4lIAogIG11dGF0ZShjbGFzc2NvZGUgPSB0b3VwcGVyKGNsYXNzY29kZSkpICU+JSAKICAgIGxlZnRfam9pbihsaWZlX2hpc3RvcnlfZGF0YSwgYnkgPSAnY2xhc3Njb2RlJykgJT4lIAogIGxlZnRfam9pbih0ZW1wZXJhdHVyZV9kYXRhLCBieSA9IGMoJ3NpdGUnLCdzaWRlJywneWVhcicpKSAlPiUgCiAgZmlsdGVyKGlzLm5hKHRhcmdldGVkKSA9PSBGKSAlPiUgCiAgZ3JvdXBfYnkodGFyZ2V0ZWQsIHJlZ2lvbiwgeWVhcikgJT4lIAogIHN1bW1hcmlzZShsb2dfbWVhbl9iaW9tYXNzID0gbG9nKG1lYW4oYmlvbWFzcywgbmEucm0gPSBUKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhbl90ZW1wID0gbWVhbihtZWFuX3RlbXAsIG5hLnJtID0gVCkpICU+JSAKICBzcHJlYWQodGFyZ2V0ZWQsIGxvZ19tZWFuX2Jpb21hc3MpICU+JSAKICBncm91cF9ieShyZWdpb24pICU+JSAKICBtdXRhdGUobWJfbGFnMSA9IGRwbHlyOjpsYWcoVGFyZ2V0ZWQsMSksCiAgICAgICAgIG1iX2xhZzIgPSBkcGx5cjo6bGFnKFRhcmdldGVkLCAyKSwKICAgICAgICAgbWJfbGFnMyA9IGRwbHlyOjpsYWcoVGFyZ2V0ZWQsIDMpLAogICAgICAgICBtYl9sYWc0ID0gZHBseXI6OmxhZyhUYXJnZXRlZCwgNCksCiAgICAgICAgIHRlbXBfbGFnMSA9IGRwbHlyOjpsYWcobWVhbl90ZW1wLDEpLAogICAgICAgICB0ZW1wX2xhZzIgPSBkcGx5cjo6bGFnKG1lYW5fdGVtcCwgMiksCiAgICAgICAgIHRlbXBfbGFnMyA9IGRwbHlyOjpsYWcobWVhbl90ZW1wLCAzKSwKICAgICAgICAgdGVtcF9sYWc0ID0gZHBseXI6OmxhZyhtZWFuX3RlbXAsIDQpCiAgICAgICAgICkKCmxpYnJhcnkocnN0YW5hcm0pCnRyb3BoaWNfcmVnIDwtIHN0YW5fZ2xtZXIoYE5vbi10YXJnZXRlZGAgfiBUYXJnZXRlZCArIG1iX2xhZzEgKyBtYl9sYWcyICsgbWJfbGFnMyArIG1iX2xhZzQgKyAKICAgICAgICAgICAgICAgICAgICBtZWFuX3RlbXAgKyAoIDEgfHllYXIpICsgdGVtcF9sYWcxICsgdGVtcF9sYWcyICsgdGVtcF9sYWczICsgdGVtcF9sYWc0LCBkYXRhID0gdHJvcGhpY19kYXRhICkKCiMgbGF1bmNoX3NoaW55c3Rhbih0cm9waGljX3JlZykKCnN1bW1hcnkodHJvcGhpY19yZWcpCgpwb3N0X2ludGVydmFsIDwtIHRyb3BoaWNfcmVnICU+JSAKICBwb3N0ZXJpb3JfaW50ZXJ2YWwoKQoKcG9zdF92YXJzIDwtIHJvdy5uYW1lcyhwb3N0X2ludGVydmFsKQoKcG9zdF9pbnRlcnZhbCA8LSBwb3N0X2ludGVydmFsICU+JSAKICBhc19kYXRhX2ZyYW1lKCkgJT4lIAogIG11dGF0ZSh0ZXJtID0gcG9zdF92YXJzKQoKdHJvcGhpY19yZWcgJT4lIAogIHBvc3Rlcmlvcl9pbnRlcnZhbCgpICU+JSAKICBhc19kYXRhX2ZyYW1lKHJvdy5uYW1lcyA9IHJvd25hbWVzKC4pKQoKcmVnX3Bsb3QgPC0gdHJvcGhpY19yZWcgJT4lIAogIHRpZHkoKSAlPiUgCiAgZ2dwbG90KCkgKyAKICBnZW9tX3BvaW50KGFlcyh0ZXJtLCBlc3RpbWF0ZSkpICsgCiAgZ2VvbV9lcnJvcmJhcihkYXRhID0gcG9zdF9pbnRlcnZhbCAKICAgICAgICAgICAgICAsIGFlcyh0ZXJtLCB5bWluID0gYDUlYCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5bWF4ID0gYDk1JWApKSArCiAgY29vcmRfZmxpcCgpCgpyZWdfcGxvdAoKYGBgCgpJbnRlcmVzdGluZywgc29tZSBldmlkZW5jZSBvZiBlZmZlY3QgYnV0IGl0J3MgbWVzc3ksIGFuZCBkZXBlbmRzIGEgbG90IG9uIG1vZGVsIHNwZWNpZmljYXRpb24uIAoKIyMgRWwgTmnDsW8KCgpgYGB7cn0KCmEgPSByZWFkX2h0bWwoJ2h0dHBzOi8vd3d3LmVzcmwubm9hYS5nb3YvcHNkL2Vuc28vbWVpL3RhYmxlLmh0bWwnKSAlPiUgCiAgaHRtbF9ub2RlKCdib2R5JykgJT4lIAogIGh0bWxfdGV4dCgpCgoKZW5zbyA8LSByZWFkX2xpbmVzKCdodHRwczovL3d3dy5lc3JsLm5vYWEuZ292L3BzZC9lbnNvL21laS90YWJsZS5odG1sJykKCmVuc28gPC0gZW5zb1tzdHJfZGV0ZWN0KGVuc28sJ1x0fChZRUFSKScpXSAlPiUgCiAgd3JpdGUoJ2Vuc28udHh0JykKCmVuc28gPC0gIHJlYWQuY3N2KCdlbnNvLnR4dCcsIHNlcCA9ICdcdCcsIGhlYWRlciA9IEYpCgp0YWJsZV9uYW1lcyA8LSBlbnNvJFYxWzFdICU+JSAKICBhcy5jaGFyYWN0ZXIoKSAlPiUgCiAgc3RyX3NwbGl0KGJvdW5kYXJ5KCd3b3JkJyksIHNpbXBsaWZ5ID0gVCkgJT4lIAogIGFzLmNoYXJhY3RlcigpICU+JSAKICB0b2xvd2VyKCkKCmVuc28gPC0gZW5zbyAlPiUgCiAgc2xpY2UoLTEpICU+JSAKICBhc19kYXRhX2ZyYW1lKCkKCmNvbG5hbWVzKGVuc28pIDwtICB0YWJsZV9uYW1lcwoKZW5zbyA8LSBlbnNvICU+JSAKICBnYXRoZXIoJ2JpbW9udGgnLCdlbnNvJywteWVhcikKCmVuc28gJT4lIAogIG11dGF0ZSh5ZWFyID0geWVhciAlPiUgYXMuY2hhcmFjdGVyKCkgJT4lIGFzLm51bWVyaWMoKSkgJT4lIAogIGdyb3VwX2J5KHllYXIpICU+JSAKICBzdW1tYXJpc2UobWVhbl9lbnNvID0gbWVhbihlbnNvKSkgJT4lIAogIGdncGxvdChhZXMoeWVhciwgbWVhbl9lbnNvKSkgKyAKICBnZW9tX3BvaW50KCkKCiBlbnNvIDwtIHJlYWRfdGFibGUoImh0dHA6Ly93d3cuZXNybC5ub2FhLmdvdi9wc2QvZ2Nvc193Z3NwL1RpbWVzZXJpZXMvRGF0YS9uaW5vMzQubG9uZy5hbm9tLmRhdGEiLAogICAgICAgICAgICBuYSA9IGMoIi05OS45OSIsICI5OS45OSIsJy05OScpLCBza2lwID0gMSwgbl9tYXggPSBsdWJyaWRhdGU6OnllYXIoU3lzLnRpbWUoKSkgLSAxODcwICsgMSwKICAgICAgICAgICAgY29sX25hbWVzID0gYygieWVhciIsIDE6MTIpKSAlPiUKIGdhdGhlcihtb250aCwgZW5zbywgLXllYXIpICU+JQogbXV0YXRlKG1vbnRoID0gYXMuZG91YmxlKG1vbnRoKSkKCmBgYAoKIyMgR2V0IFBETwoKYGBge3J9CgogcGRvIDwtIHJlYWRfdGFibGUoImh0dHBzOi8vd3d3LmVzcmwubm9hYS5nb3YvcHNkL2djb3Nfd2dzcC9UaW1lc2VyaWVzL0RhdGEvcGRvLmxvbmcuZGF0YSIsCiAgICAgICAgICAgIG5hID0gYygiLTk5Ljk5IiwgIjk5Ljk5IiwnLTk5JyksIHNraXAgPSAxLCBuX21heCA9IGx1YnJpZGF0ZTo6eWVhcihTeXMudGltZSgpKSAtIDE5MDAsCiAgICAgICAgICAgIGNvbF9uYW1lcyA9IGMoInllYXIiLCAxOjEyKSkgJT4lCiBnYXRoZXIobW9udGgsIHBkbywgLXllYXIpICU+JQogbXV0YXRlKG1vbnRoID0gYXMuZG91YmxlKG1vbnRoKSwKICAgICAgICBkYXRlID0gbHVicmlkYXRlOjp5bWQocGFzdGUoeWVhcixtb250aCwnMDEnLCBzZXAgPSAnLScpKSkKCnBkbyAlPiUgCiAgZmlsdGVyKHllYXIgPj0gMjAwMCkgJT4lIAogIGdncGxvdChhZXMoZGF0ZSxwZG8pKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDApLCBsaW5ldHlwZSA9IDIpICsKICBnZW9tX3BvaW50KCkKCgpgYGAKCgoKIyMgQ2F1c2FsIGRlZmVuc2UgaWRlYXMKCkhvdyBjYW4geW91IGRlZmVuZCB0aGUgY2F1c2FsIG5hdHVyZSBvZiB0aGUgcmVzdWx0cz8KCkluY2x1ZGUgYSAibGVhZCIgb24gdGhlIERpRCB0ZXJtOiBUaGlzIGlzIHR1cm5lZCBvbiBpbiB0aGUgeWVhcnMgbGVhZGluZyB1cCB0byB0aGUgcG9saWN5LCBhbmQgc2F5cyB0aGF0IHRoZSBwb2xpY3kgaXMgZ29pbmcgdG8gaGFwcGVuLiBTSG91bGQgYmUgaW5zaWduaWZpY2FudCBpZiB0aGUgbW9kZWwgaXMgcmlnaHQuIExvb2sgYmFjayBhdCBtb3N0bHkgaGFybWxlc3MgYW5kIE9saXZpZXIncyBub3RlCgpIb3cgd2VsbCBkb2VzIG91dC1vZi1zYW1wbGUgcHJlZGljdGlvbiBoZWxwIHlvdSB3aXRoIGNhdXNhbGl0eT8gQXQgaXQncyBmYWNlIGl0IGdpdmVzIGV2aWRlbmNlIHRoYXQgeW91ciBtb2RlbCBpcyBkb2luZyBhIGdvb2Qgam9iIG9mIGRlc2NyaWJpbmcgdGhlIGRhdGEuIEJ1dCBkb2VzIGl0IGltcGx5IGhlbHAgd2l0aCBjYXVzYWxpdHk/IFN1cHBvc2UgeW91IGhhZCBhIG1vZGVsIHRoYXQgc2FpZCBwcmVkaWN0IGlmIGl0J3MgcmFpbmluZyBvdXRzaWRlIGJhc2VkIG9uIHVtYnJlbGxhcy4gSXQncyBvdXQgb2Ygc2FtcGxlIHByZWRpY3Rpb24gd291bGQgYmUgZ3JlYXQsIGJ1dCB0aGF0IGRvZXNuJ3QgbWVhbiB0aGF0IG9wZW5pbmcgdW1icmVsbGFzIGlzIGdvaW5nIHRvIGNhdXNlIHJhaW4uIAoKIyMgUmVncmVzc2lvbiBFeHBsb3JhdGlvbgoKR29hbCBvZiB0aGlzIHNlY3Rpb24gaXMgdG8gc3RhcnQgcmVhbGx5IGRpZ2dpbmcgaW50byB0aGUgcmVncmVzc2lvbnMuCgojIyMgRGF0YSBFeHBsb3JhdGlvbgoKTGV0J3Mgc3RpY2sgd2l0aCBKZW4ncyBkYXRhIGZvciBub3csIGJ1dCBjb2duaXphbnQgdGhhdCB5b3UgbmVlZCB0byBsb29rIGludG8gcmVwcm9kdWNpbmcgYW5kIHNlbnNpdGl2aXRpZXMgdG8gdHJhbnNmb3JtYXRpb24gYXNzdW1wdGlvbnMKClB1bGxpbmcgaW4gSmVuJ3MgZGVuc2l0eSBkYXRhLCBtZXJnaW5nIHNvbWUgdXNlZnVsIHRlbXBlcmF0dXJlLCBzaXRlLCBsaWZlIGhpc3RvcnksIGVuc28sIGFuZCBQRE8gZGF0YQoKYGBge3IgbG9hZCBkYXRhIGFnYWlufQoKZGVuc2l0eV9kYXRhIDwtIHJlYWRfY3N2KCcuLi9kYXRhL2NpX3Jlc2VydmVfZGF0YV9maW5hbDMgdHh0LmNzdicpICU+JQogIG1hZ3JpdHRyOjpzZXRfY29sbmFtZXMoLix0b2xvd2VyKGNvbG5hbWVzKC4pKSkgJT4lIAogIGdhdGhlcignY29uY2F0Lm5hbWUnLCd2YWx1ZScsIGdyZXAoJ18nLGNvbG5hbWVzKC4pKSxjb252ZXJ0ID0gVCkgJT4lCiAgbXV0YXRlKGRhdGEudHlwZSA9IGdzdWIoJ1xcXy4qJywgJycsIGNvbmNhdC5uYW1lKSwKICAgICAgICAgY2xhc3Njb2RlID0gZ3N1YignLipcXF8nLCcnLGNvbmNhdC5uYW1lKSkgJT4lCiAgbXV0YXRlKHZhbHVlID0gYXMubnVtZXJpYyh2YWx1ZSkpICU+JQogIHNwcmVhZChkYXRhLnR5cGUsdmFsdWUpICU+JQogIHJlbmFtZShzaXRlX3NpZGUgPSBzaXRlLnNpZGUpCgpsZW5ndGhfZGF0YSA8LSByZWFkX2NzdignLi4vZGF0YS9VQ1NCX0ZJU0ggcmF3IHRocnUgMjAxMy5jc3YnKSAlPiUgCiAgICBtYWdyaXR0cjo6c2V0X2NvbG5hbWVzKC4sdG9sb3dlcihjb2xuYW1lcyguKSkpCgp0ZW1wZXJhdHVyZV9kYXRhIDwtIGxlbmd0aF9kYXRhICU+JSAKICBncm91cF9ieShzaXRlLHNpZGUseWVhcikgJT4lIAogIHN1bW1hcmlzZShtZWFuX3RlbXAgPSBtZWFuKHRlbXAsIG5hLnJtID0gVCkpCgpsaWZlX2hpc3RvcnlfZGF0YSA8LSByZWFkX2NzdignLi4vZGF0YS9WUkcgRmlzaCBMaWZlIEhpc3RvcnkgaW4gTVBBXzA0XzA4XzExXzEyIDExLU1hci0yMDE0LmNzdicpICU+JQogIHJlbmFtZShjbGFzc2NvZGUgPSBwaXNjb19jbGFzc2NvZGUpICU+JQogIG11dGF0ZShjbGFzc2NvZGUgPSB0b2xvd2VyKGNsYXNzY29kZSkpICU+JSAKICBtYWdyaXR0cjo6c2V0X2NvbG5hbWVzKC4sdG9sb3dlcihjb2xuYW1lcyguKSkpCgpsaWZlX25hbWVzIDwtIGMoJ2NsYXNzY29kZScsY29sbmFtZXMobGlmZV9oaXN0b3J5X2RhdGEpWyFjb2xuYW1lcyhsaWZlX2hpc3RvcnlfZGF0YSkgJWluJSBjb2xuYW1lcyhkZW5zaXR5X2RhdGEpXSkKCmxpZmVfaGlzdG9yeV9kYXRhIDwtIGxpZmVfaGlzdG9yeV9kYXRhWyAsIGxpZmVfbmFtZXNdCgpzaXRlX2RhdGEgPC0gcmVhZF9jc3YoJy4uL2RhdGEvRmluYWxfU2l0ZV9UYWJsZV9VQ1NCLmNzdicpICU+JQogICAgbWFncml0dHI6OnNldF9jb2xuYW1lcyguLHRvbG93ZXIoY29sbmFtZXMoLikpKQoKc2l0ZV9uYW1lcyA8LSBjKCdzaXRlJywnc2lkZScsY29sbmFtZXMoc2l0ZV9kYXRhKVshY29sbmFtZXMoc2l0ZV9kYXRhKSAlaW4lIGNvbG5hbWVzKGRlbnNpdHlfZGF0YSldKQoKc2l0ZV9kYXRhIDwtIHNpdGVfZGF0YVssc2l0ZV9uYW1lc10KCmVuc28gPC0gcmVhZF9jc3YoJy4uL2RhdGEvZW5zby5jc3YnKSAlPiUgCiAgZ3JvdXBfYnkoeWVhcikgJT4lIAogIHN1bW1hcmlzZShtZWFuX2Vuc28gPSBtZWFuKGVuc28sIG5hLnJtID0gVCkpCgpwZG8gPC0gcmVhZF9jc3YoJy4uL2RhdGEvcGRvLmNzdicpICU+JSAKZ3JvdXBfYnkoeWVhcikgJT4lIAogIHN1bW1hcmlzZShtZWFuX3BkbyA9IG1lYW4ocGRvLCBuYS5ybSA9IFQpKQoKY29tcF9kYXRhIDwtIGRlbnNpdHlfZGF0YSAlPiUgCiAgbGVmdF9qb2luKHRlbXBlcmF0dXJlX2RhdGEsIGJ5ID0gYygnc2l0ZScsJ3NpZGUnLCd5ZWFyJykpICU+JSAKICBsZWZ0X2pvaW4obGlmZV9oaXN0b3J5X2RhdGEsIGJ5ID0gJ2NsYXNzY29kZScpICU+JSAKICBsZWZ0X2pvaW4oc2l0ZV9kYXRhLCBieSA9IGMoJ3NpdGUnLCdzaWRlJykpICU+JSAKICBsZWZ0X2pvaW4oZW5zbywgYnkgPSAneWVhcicpICU+JSAKICBsZWZ0X2pvaW4ocGRvLCBieSA9ICd5ZWFyJykKICAKYGBgCgojIyMgRGF0YSBDb21wb3NpdGlvbgoKTGV0J3MgbG9vayBhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIHNhbXBsZSBzaXplIG92ZXIgdGltZTsgd2hlcmUgYXJlIHlvdXIgZGF0YSBjb21pbmcgZnJvbT8KCmBgYHtyfQoKY29tcF9kYXRhICU+JSAKICBncm91cF9ieSh5ZWFyKSAlPiUgCiAgc3VtbWFyaXNlKG51bV9vYnMgPSBsZW5ndGgoYmlvbWFzcykpICU+JSAKICBnZ3Bsb3QoYWVzKHllYXIsIG51bV9vYnMpKSArIAogIGdlb21fcG9pbnQoKQogIApgYGAKCmBgYHtyfQpjb21wX2RhdGEgJT4lIAogIGdyb3VwX2J5KHllYXIsdGFyZ2V0ZWQpICU+JSAKICBzdW1tYXJpc2UobnVtX29icyA9IGxlbmd0aChiaW9tYXNzKSkgJT4lIAogIGdncGxvdChhZXMoeWVhciwgbnVtX29icywgZmlsbCA9IHRhcmdldGVkKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykKCgpgYGAKCkh1aCwgc28gYSBidW5jaCBvZiB0aGUgb2JzZXJ2YXRpb25zIGFyZSAidW5rbm93biIgb24gdGFyZ2V0aW5nIHN0YXR1cy4gTGV0J3MgbG9vayBpbnRvIHRoaXMuIEJleW9uZCB0aGF0IHRob3VnaCwgdGhlIHRhcmdldGVkIGFuZCBub24tdGFyZ2V0ZWQgYXJlIGZhaXJseSB3ZWxsIGJhbGFuY2VkLiAKCmBgYHtyfQoKaHVoIDwtIGNvbXBfZGF0YSAlPiUgCiAgZmlsdGVyKGlzLm5hKHRhcmdldGVkKSkKCnNvcnQodW5pcXVlKGh1aCRjbGFzc2NvZGUpKQoKYGBgCkFoYSwgdGhlc2UgYXBwZWFyIHRvIGJlIGEgYSBidW5jaCBvZiBtaXNjLiBjcml0dGVycyBhbmQgY2xhc3NpZmljYXRpb24gZm9yIHVuZGVyc3RvcnkgY292ZXIuIEFzbG8gInlvdW5nIG9mIHRoZSB5ZWFyIi4gUHJvYmFibHkgYmVzdCB0byBmaWx0ZXIgdGhlc2UgZ3V5cyBvdXQuIAoKYGBge3J9Cgpjb21wX2RhdGEgJT4lIAogIGZpbHRlcihpcy5uYShjb21tb25uYW1lKSA9PSBGKSAlPiUgCiAgIGdyb3VwX2J5KHllYXIpICU+JSAKICBzdW1tYXJpc2UobnVtX29icyA9IGxlbmd0aChiaW9tYXNzKSkgJT4lIAogIGdncGxvdChhZXMoeWVhciwgbnVtX29icykpICsgCiAgZ2VvbV9wb2ludCgpCiAgCmBgYAoKYGBge3J9Cgpjb21wX2RhdGEgJT4lIAogIGZpbHRlcihpcy5uYShjb21tb25uYW1lKSA9PSBGKSAlPiUgCiAgZ3JvdXBfYnkoeWVhcixyZWdpb24pICU+JSAKICBzdW1tYXJpc2UobnVtX29icyA9IGxlbmd0aChiaW9tYXNzKSkgJT4lIAogIGdncGxvdChhZXMoeWVhciwgbnVtX29icywgZmlsbCA9IHJlZ2lvbikpICsgCiAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpCgpgYGAKSHVoLCB3b3J0aCBub3RpbmcgdGhhdCBhIGZldyBvZiB0aGUgaXNsYW5kcyBvbmx5IGNvbWUgaW4gYWZ0ZXIgMjAwMy4gV2hhdCBpcyB0aGlzIGRvaW5nIHRvIHlvdXIgZWZmZWN0IHRoYXQgeW91J3JlIGJhc2ljYWxseSBicmluaW5nIGluIGEgYnVuY2ggb2YgbmV3IGlzbGFuZHMgd2l0aCBkaWZmZXJlbnQgZWZmZWN0cyByaWdodCBhZnRlciBpbXBsZW1lbnRhdGlvbiBvZiBNUEFzIGluIDIwMDM/CgpgYGB7cn0KCmNvbXBfZGF0YSAlPiUgCiAgZmlsdGVyKGlzLm5hKGNvbW1vbm5hbWUpID09IEYpICU+JSAKICBncm91cF9ieSh5ZWFyLGJyb2FkdHJvcGhpYykgJT4lIAogIHN1bW1hcmlzZShudW1fb2JzID0gbGVuZ3RoKGJpb21hc3MpKSAlPiUgCiAgZ2dwbG90KGFlcyh5ZWFyLCBudW1fb2JzLCBmaWxsID0gYnJvYWR0cm9waGljKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykKCmBgYAoKCgojIyMgRWZmZWN0IEV4cGxvcmF0aW9uCgpMZXQncyBsb29rIGF0IHRoZSBjaGFuZ2UgaW4gZGVuc2l0eSBhcyBhIGZ1bmN0aW5vIG9mIGEgdmFyaWV0eSBvZiB2YXJpYWJsZXMKCmBgYHtyfQoKY2FuZGlkYXRlcyA8LSBjKCdiaW9tYXNzJywneWVhcicsJ3NpdGUnLCdzaWRlJywnY2xhc3Njb2RlJywKICAgICAgICAgICAgICAgICdyZWdpb24nLCdicm9hZHRyb3BoaWMnLCdyZXNlcnZlJywnY2FtcHVzJywnbXBhYXJlYW5tMicsJ21lYW5fdGVtcCcsJ2d1aWxkJywndHJvcGhpY2dyb3VwJywndGFyZ2V0ZWQnLAogICAgICAgICAgICAgICAgJ21lYW5fZW5zbycsJ21lYW5fcGRvJywndmJnZi5rJywndmJnZi5saW5mJywnbWF4X2xlbmd0aF9maXNoYmFzZScpCgpyZWdfZGF0YSA8LSBjb21wX2RhdGFbLGNhbmRpZGF0ZXNdICU+JSAKICBmaWx0ZXIoaXMubmEoYmlvbWFzcykgPT0gMCwgaXMubmEodGFyZ2V0ZWQpID09IEYpICU+JSAKICBtdXRhdGUobG9nX2RlbnNpdHkgPSBsb2coYmlvbWFzcyksCiAgICAgICAgIGZhY3Rvcl95ZWFyID0gYXMuZmFjdG9yKHllYXIpLAogICAgICAgICB0YXJnZXRlZCA9IGFzLm51bWVyaWModGFyZ2V0ZWQgPT0gJ1RhcmdldGVkJyksCiAgICAgICAgIHBvc3RfbWxwYSA9IGFzLm51bWVyaWMoeWVhciA+PSAyMDAzKSwKICAgICAgICAgcmVzZXJ2ZSA9IGFzLm51bWVyaWMocmVzZXJ2ZSA9PSAnSU4nKSwKICAgICAgICAgZGlkID0gYXMuZmFjdG9yKHRhcmdldGVkICogcG9zdF9tbHBhICogeWVhcikKICAgICAgICAgKQoKYGBgCgpgYGB7cn0KCnJlZ19kYXRhICU+JSAKICBncm91cF9ieSh5ZWFyLHRhcmdldGVkKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5fZGVuc2l0eSA9IG1lYW4oYmlvbWFzcywgbmEucm0gPSBUKSkgJT4lIAogIGdncGxvdChhZXMoeWVhcixtZWFuX2RlbnNpdHksIGNvbG9yID0gZmFjdG9yKHRhcmdldGVkKSkpICsgCiAgZ2VvbV9saW5lKCkKCmBgYAoKYGBge3J9CgpyZWdfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoeWVhcix0YXJnZXRlZCxyZWdpb24pICU+JSAKICBzdW1tYXJpc2UobWVhbl9kZW5zaXR5ID0gbWVhbihsb2coYmlvbWFzcyArIDFlLTMpLCBuYS5ybSA9IFQpKSAlPiUgCiAgZ2dwbG90KGFlcyh5ZWFyLG1lYW5fZGVuc2l0eSwgY29sb3IgPSBmYWN0b3IodGFyZ2V0ZWQpKSkgKyAKICBnZW9tX2xpbmUoKSArIAogIGZhY2V0X3dyYXAofnJlZ2lvbikgKyAKICB5bGFiKCdsb2cgbWVhbiBkZW5zaXR5JykKCmBgYAoKT25lIHRyb3VibGluZyBwYXR0ZXJuLCBib3RoIEFOQSBhbmQgU0NJIHNob3cgdGhhdCBzdGVlcCBkcm9wIGluIGRlbnNpdGllcyBmcm9tIDIwMDAtMjAwMywgd2hpY2ggbWlnaHQgcmVhbGx5IGJlIHNrZXdpbmcgdGhlIGVmZmVjdCBvZiB0aGUgTVBBcyAodGhhdCBlYXJseSBuZWdhdGl2ZSBlZmZlY3QpLCB0aG91Z2ggb24gdGhlIHBsdXMgc2lkZSBpdCdzIGJvdGggdGFyZ2V0dGVkIGFuZCBub24tdGFyZ2V0ZWQgCgpMZXQncyBsb29rIGF0IHNvbWUgb3RoZXIgZmFjdG9ycyBoZXJlCgpgYGB7cn0KCnJlZ19kYXRhICU+JSAKICBncm91cF9ieShicm9hZHRyb3BoaWMpICU+JSAKICBzdW1tYXJpc2UobWVhbl9kZW5zaXR5ID0gbWVhbihiaW9tYXNzLCBuYS5ybSA9IFQpKSAlPiUgCiAgZ2dwbG90KGFlcyhicm9hZHRyb3BoaWMsbWVhbl9kZW5zaXR5LCBmaWxsID0gYnJvYWR0cm9waGljKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JykKCmBgYApObyBzdXJwcmlzZXMsIGhpZ2hlciBkZW5zaXR5IG9mIGhlcmJpdm9yZXMKCmBgYHtyfQoKcmVnX2RhdGEgJT4lIAogIGdyb3VwX2J5KHJlZ2lvbikgJT4lIAogIGdncGxvdChhZXMocmVnaW9uLGJpb21hc3MsIGZpbGwgPSByZWdpb24pKSArIAogIGdlb21fYm94cGxvdCgpCgpgYGAKCmBgYHtyfQpyZWdfZGF0YSAlPiUgCiAgc2VsZWN0KGJpb21hc3MseWVhcixtZWFuX3RlbXAsIG1lYW5fcGRvLCBtZWFuX2Vuc28pICU+JSAKICBnYXRoZXIobWV0cmljLHZhbHVlLCBjb250YWlucygnbWVhbicpKSAlPiUgCiAgZ3JvdXBfYnkoeWVhcixtZXRyaWMpICU+JSAKICBzdW1tYXJpc2UobWVhbl9iaW9tYXNzID0gbG9nKG1lYW4oYmlvbWFzcywgbmEucm0gPSBUKSksIG1lYW5fdmFsdWUgPSBtZWFuKHZhbHVlLCBuYS5ybSA9IFQpKSAlPiUgCiAgZ2dwbG90KGFlcyhtZWFuX3ZhbHVlLG1lYW5fYmlvbWFzcywgZmlsbCA9IG1ldHJpYykpICsgCiAgZ2VvbV9hYmxpbmUoYWVzKGludGVyY2VwdCA9IG1lYW4obWVhbl9iaW9tYXNzLCBuYS5ybSA9IFQpLCBzbG9wZSA9IDApKSArIAogIGdlb21fcG9pbnQoc2hhcGUgPSAyMSkgKyAKICBmYWNldF93cmFwKH5tZXRyaWMsIHNjYWxlcyA9ICdmcmVlX3gnKQpgYGAKCkludGVyZXN0aW5nLCBkZWZpbml0ZWx5IHNvbWUgbm9pc2UgaW4gaGVyZSwgYnV0IHNlZW1zIHRvIGEgYSB0cmVuZCB0b3dhcmRzIHRoZSAibWVhbiIgb2YgdGhlIGVudmlyb25tZW50YWwgY292YXJpYXRlcy4gR29vZCBldmlkZW5jZSBmb3IgdGhyb3dpbmcgYSBxdWFkcmF0aWMgaW4gaGVyZS4gCgpgYGB7cn0KCmVudmlyb25tZW50YWxfY29yID0gcmVnX2RhdGEgJT4lIAogIGZpbHRlcihpcy5uYShtZWFuX3RlbXApID09IEYpICU+JSAKICBzZWxlY3QobWVhbl90ZW1wLCBtZWFuX2Vuc28sIG1lYW5fcGRvLCB5ZWFyKSAlPiUKICBjb3IoKSAKCmNvcnJwbG90Ojpjb3JycGxvdChlbnZpcm9ubWVudGFsX2NvcikKCmBgYApRdWl0ZSBhIGJpdCBvZiBjb3JyZWxhdGlvbiBiZXR3ZWVuIHNvbWUgb2YgdGhlIGVudmlyb25tZW50YWwgdmFyaWFibGVzLCBidXQgeW91IGRvbid0IHJlYWxseSBjYXJlIGFib3V0IGVzdGltYXRpbmcgdGhvc2UgcHJlY2lzZWx5IHNvIG5vdCBhIGh1Z2UgZGVhbC4gCgpCdXQsIHRoZSB5ZWFyIHRoaW5nIGNvdWxkIGJlIGEgYml0IG1lc3N5LCBzaW5jZSB5b3UgaGF2ZSBzdWNoIHBvb3IgY29udHJhc3QgYmVmb3JlIGFuZCBhZnRlciBNUEEsIHNvIG1pZ2h0IG5lZWQgdG8gbG9vayBhdCBtZWFuIFBETyBhcyBhIHByb2JsZW0gdmFyaWFibGUuIAoKIyMjIERpRCBTdHJ1Y3R1cmUKCk5vdywgd2hhdCBzaG91bGQgdGhlIGFjdHVhbCBkaWZmZXJlbmNlIGluIGRpZmZlcmVuY2UgbG9vayBsaWtlPwoKVGhlIGtleSB0aGluZyB5b3UgbmVlZCBpcyB0cmVhdG1lbnQgb24gdGhlIHRyZWF0ZWQsIHNvIHRoYXQncyBiZWluZyBhIGZpc2hlZCBzcGVjaWVzIHBvc3QgMjAwMy4gCgpJZiB5b3UgaW5jbHVkZSBzcGVjaWVzIHNwZWNpZmljIGZpeGVkIGVmZmVjdHMsIHRoZW4geW91IGRvbid0IGhhdmUgdG8gaW5jbHVkZSB0aGUgZ2VuZXJhbCBlZmZlY3Qgb2YgYmVpbmcgYSBmaXNoZWQgc3BlY2llcywgc2luY2UgdGhvc2Ugd2lsbCBhbGwgY29tZSBvdXQgaW4gdGhlIHdhc2ggKGkuZS4gdGhlIGZpc2hlZCBlZmZlY3QgaXMgaW50ZXJuYWxpemVkIGluIHRoZSBzcGVjaWVzIHNwZWNpZmljIGZpeGVkIGVmZmVjdHMsIG9yIGFsdGVybmF0aXZlbHksIHlvdSBzYXkgdGhhdCB0aGUgc3BlY2llcyBsZXZlbCBlZmZlY3QgaXMgYSBmdW5jdGlvbiBvZiBjb3ZhcmlhdGVzLCBpbmNsdWRpbmcgYmVpbmcgZmlzaGVkKQoKU2ltaWxhcmx5IHdpdGggcG9zdC1tcGEuIElmIHlvdSBkb24ndCBpbmNsdWRlIHllYXIgZml4ZWQgZWZmZWN0cywgdGhlbiB5b3UgbmVlZCBpdC4gQnV0LCBpZiB5b3UgaW5jbHVkZSB5ZWFyIGZpeGVkIGVmZmVjdHMsIHRoZW4gdGhlICJwb3N0IG1wYSIgZWZmZWN0IHNob3VsZCBiZSBzb2FrZWQgdXAsIGFuZCBpbiBmYWN0IHBlcmZlY3RseSBjb2xpbmVhciB3aXRoLCB0aGUgeWVhciBmaXhlZCBlZmZlY3RzLiAKClNvLCBub3csIHRoZSByZWFsIHBhaW4gaW4gdGhlIGFzcyBpcyB0aGUgeWVhciB0ZXJtcy4gV2hpY2ggSSB0aGluayB5b3UgZmlndXJlZCBvdXQhIAoKVGhlIHF1ZXN0aW9uIHRoZW4gaXMgaG93IGRvIHlvdSBjb250cm9sIGZvciBvdGhlciB0aGluZ3MuIAoKWW91IGNvdWxkIGp1c3QgaW5jbHVkZSB0aGUgRGlEIHRlcm0gCgojIyMgQmFyZS1ib25lcyByZWdyZXNzaW9uCgpMZXQncyBzdGFydCB3aXRoIGEgYmFyZSBib25lcyByZWdyZXNzaW9uLCB1c2luZyBgcnN0YW5hcm1gLCBvbmUgaGllcmFyY2hpY2hhbCwgb25lIG5vdC4gWW91J2xsIHRoZW4gY29tcGFyZSB5b3VyIHJlc3VsdHMgdG8gb25lIHdoZXJlIHlvdSBjb2RlIHRoZSBsaWtlbGlob29kIHlvdXJzZWxmIAoKYGBge3IsIGV2YWwgPSBGfQoKcmVnX3ZhcnMgPC0gYygnbG9nX2RlbnNpdHknLCdmYWN0b3JfeWVhcicsICd5ZWFyJywndGFyZ2V0ZWQnLCAnZGlkJywgJ3JlZ2lvbicgLAonbWVhbl9lbnNvJywnbWVhbl9wZG8nLCAnbWVhbl90ZW1wJywnY2xhc3Njb2RlJywnc2l0ZScsJ3NpZGUnLCdwb3N0X21scGEnLCdyZWdpb24nLAonYnJvYWR0cm9waGljJykKCmhhc19hbGwgPC0gZnVuY3Rpb24oeCkgYW55KGlzLm5hKHgpKSA9PSBGCgpwb3NfcmVnX2RhdGEgPC0gcmVnX2RhdGEgJT4lIAogIHNlbGVjdCgtbWVhbl90ZW1wKSAlPiUgCiAgbGVmdF9qb2luKGNvbmRpdGlvbnNfZGF0YSAlPiUgc2VsZWN0KHNpdGUsc2lkZSx5ZWFyLCBjb250YWlucygnbWVhbicpKSwgYnkgPSBjKCdzaXRlJywnc2lkZScsJ3llYXInKSkgJT4lIAogIGZpbHRlcihiaW9tYXNzID4wLCB5ZWFyID49MjAwMCkgJT4lIAogIHNlbGVjdF8oLmRvdHMgPSBhcy5saXN0KHJlZ192YXJzKSkgJT4lIAogIG11dGF0ZShoYXNfYWxsX3ZhcnMgPSBhcHBseSguLDEsaGFzX2FsbCkpICU+JSAKICBmaWx0ZXIoaGFzX2FsbF92YXJzID09IFQpICU+JSAKICBtYXAyX2RmKGNvbG5hbWVzKC4pLCBjZW50ZXJfc2NhbGUsIG9taXRfbmFtZXMgPSBjKCdsb2dfZGVuc2l0eScsJ3llYXInLCdtZWFuX2Vuc28nLCdtZWFuX3BkbycpKSAlPiUKICBtdXRhdGUoZGlkX2R1bW15ID0gMSAqIHRhcmdldGVkLAogICAgICAgICBkaWRfeWVhciA9IHBhc3RlKCdkaWQnLHllYXIsIHNlcCA9ICdfJykpICU+JSAKICBzcHJlYWQoZGlkX3llYXIsZGlkX2R1bW15LCBmaWxsID0gMCkgJT4lIAogIG11dGF0ZSh0ZW1wMiA9IG1lYW5fdGVtcF4yLAogICAgICAgICBwZG8yID0gbWVhbl9wZG9eMiwKICAgICAgICAgZW5zbzIgPSBtZWFuX2Vuc29eMiwKICAgICAgICAgc2l0ZV9zaWRlID0gcGFzdGUoc2l0ZSwgc2lkZSwgc2VwID0gJ18nKSkKCiMgcG9zX3JlZ19kYXRhJGRpZF8yMDAzW3Bvc19yZWdfZGF0YSRkaWRfMjAwMyA9PSAxXSA8LSAgMC41Cgpwb3NfcmVnX2RhdGEgJT4lIAogIGdyb3VwX2J5KGZhY3Rvcl95ZWFyLHRhcmdldGVkKSAlPiUgCiAgc3VtbWFyaXNlKG1iID0gbWVhbihsb2dfZGVuc2l0eSwgbmEucm0gPSBUKSkgJT4lIAogIGdncGxvdChhZXMoZmFjdG9yX3llYXIsIG1iLCBjb2xvciA9IGZhY3Rvcih0YXJnZXRlZCkpKSArIAogIGdlb21fcG9pbnQoKQoKCmRpZF95ZWFycyA8LSBwYXN0ZSgnZGlkJywyMDAwOjIwMTMsIHNlcCA9ICdfJykKCmRpZF95ZWFyIDwtIGRpZF95ZWFyc1tkaWRfeWVhcnMhPSdkaWRfMjAwMCddCgoKc2ltcGxlX3JlZyA8LQphcy5mb3JtdWxhKApwYXN0ZTAoCidsb2dfZGVuc2l0eSB+JywKcGFzdGUoZGlkX3llYXIsIGNvbGxhcHNlID0gJysnKSwKJyArICgxfHllYXIpICsgKDEgKyBtZWFuX3RlbXAgKyB0ZW1wMiB8Y2xhc3Njb2RlKSArIG1lYW5fZW5zbyArICBtZWFuX3BkbyArICgxIHwgc2l0ZV9zaWRlKSArICgxIHwgc2l0ZSkgKyAoMSB8IHJlZ2lvbikgKyB0YXJnZXRlZCArIHBvc3RfbWxwYScKKQopCgojICsgdmJnZi5saW5mICsKIyB2YmdmLmsgKwojIG1lYW5fZW5zbyArIGVuc28yICsgbWVhbl9wZG8gKyBwZG8yICsgbWVhbl90ZW1wICArIHRlbXAyJykKCmZyZXFfZmxhdF9yZWcgPC0gbG1lNDo6bG1lcihzaW1wbGVfcmVnLCBkYXRhID0gcG9zX3JlZ19kYXRhKQoKZmxhdF9yZWcgPC0gc3Rhbl9nbG1lcihzaW1wbGVfcmVnLCBkYXRhID0gcG9zX3JlZ19kYXRhLGNoYWlucyA9IDEpCgoKZnJlcV9kaWRfcGxvdCA8LSAgZnJlcV9mbGF0X3JlZyAlPiUgCiAgdGlkeSgpICU+JSAKICBtdXRhdGUobG93ZXIgPSBlc3RpbWF0ZSAtIDEuOTYgKiBzdGQuZXJyb3IsCiAgICAgICAgIHVwcGVyID0gZXN0aW1hdGUgKyAxLjk2ICogc3RkLmVycm9yKSAlPiUgCiAgZmlsdGVyKHN0cl9kZXRlY3QodGVybSwnZGlkJykpICU+JSAKICBtdXRhdGUoeWVhciA9IHN0cl9yZXBsYWNlKHRlcm0sICdkaWRfJywnJykgJT4lIGFzLm51bWVyaWMoKSkgJT4lIAogIGdncGxvdCgpICsKZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IDApKSArIAogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAyMDAzKSwgY29sb3IgPSAncmVkJywgbGluZXR5cGUgPSAyKSArCiAgZ2VvbV9wb2ludHJhbmdlKGFlcyh5ZWFyLGVzdGltYXRlLCB5bWF4ID0gdXBwZXIsIHltaW4gPSBsb3dlcikpICsgCiAgeWxhYignRXN0aW1hdGVkIE1MUEEgRWZmZWN0JykgKyAKICBnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoZGF0YSA9IGRhdGFfZnJhbWUoeCA9IDIwMDMsIHkgPSAxKSwgYWVzKHgseSwgbGFiZWwgPSAnTUxQQSBFbmFjdGVkJyksbnVkZ2VfeCA9IDIpICsgCiAgeGxhYignWWVhcicpCiAgICAgICAgIApmcmVxX2RpZF9wbG90CgpkaWRfcGxvdCA8LSBmbGF0X3JlZyAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpIAogIAogIGRpZF9wbG90IDwtIGRpZF9wbG90WyxzdHJfZGV0ZWN0KGNvbG5hbWVzKGRpZF9wbG90KSwgJ2RpZF8nKV0gJT4lIAogIGdhdGhlcihkaWQsZWZmZWN0KSAlPiUgCiAgbXV0YXRlKHllYXIgPSBzdHJfcmVwbGFjZShkaWQsJ2RpZF8nLCcnKSAlPiUgYXMubnVtZXJpYygpKSAlPiUgCiAgZ3JvdXBfYnkoeWVhcikgJT4lIAogIHN1bW1hcmlzZShtZWFuX2VmZmVjdCA9IG1lYW4oZWZmZWN0KSwKICAgICAgICAgICAgdG9wID0gc29ydChlZmZlY3QpW3JvdW5kKC45NzUgKiBsZW5ndGgoZWZmZWN0KSldLAogICAgICAgICAgICBib3R0b20gPSBzb3J0KGVmZmVjdClbcm91bmQoLjAyNSAqIGxlbmd0aChlZmZlY3QpKV0pICU+JSAKICBnZ3Bsb3QoKSArIAogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAwKSkgKyAKICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMjAwMyksIGNvbG9yID0gJ3JlZCcsIGxpbmV0eXBlID0gMikgKwogIGdlb21fcG9pbnRyYW5nZShhZXMoeWVhcixtZWFuX2VmZmVjdCwgeW1heCA9IHRvcCwgeW1pbiA9IGJvdHRvbSkpICsgCiAgeWxhYignRXN0aW1hdGVkIE1MUEEgRWZmZWN0JykgKyAKICBnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoZGF0YSA9IGRhdGFfZnJhbWUoeCA9IDIwMDMsIHkgPSAxKSwgYWVzKHgseSwgbGFiZWwgPSAnTUxQQSBFbmFjdGVkJyksbnVkZ2VfeCA9IDIpICsgCiAgeGxhYignWWVhcicpCgpkaWRfcGxvdApnZ3NhdmUoJ25ld19tbHBhX2RpZC5wZGYnLGRpZF9wbG90KQoKbXRjYXJzICU+JSAKICBtYXBfZGYoY2VudGVyX3NjYWxlKQoKYGBgCgpOb3cgbGV0J3MgdHJ5IGFuZCByZXBsaWNhdGUgd2l0aCBhIGN1c3RvbSBTVEFOIGZ1bmN0aW9uCgpgYGB7ciwgZXZhbCA9IEZ9CgpkaWRfcGxvdCA8LSBmbGF0X3JlZyAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICBzZWxlY3QoY29udGFpbnMoJ2NsYXNzY29kZScpKSAlPiUgCiAgZ2F0aGVyKGNsYXNzY29kZSxlZmZlY3QpICU+JSAKICBtdXRhdGUoY2xhc3Njb2RlID0gc3RyX3JlcGxhY2UoY2xhc3Njb2RlLCdjbGFzc2NvZGUnLCcnKSkKCnN0YW5fcmVnX2RhdGEgPC0gcG9zX3JlZ19kYXRhICU+JSAKICBtdXRhdGUoeWVhcl9tYXJrZXIgPSAxKSAlPiUgCiAgbXV0YXRlKHllYXIgPSBwYXN0ZSgneWVhcicseWVhciwgc2VwID0gJ18nKSkgJT4lIAogIHNwcmVhZCh5ZWFyLHllYXJfbWFya2VyLCBmaWxsID0gMCkgJT4lIAogIG11dGF0ZShjbGFzc2NvZGUgPSBwYXN0ZSgnY2xhc3Njb2RlJyxjbGFzc2NvZGUsIHNlcCA9ICdfJyksCiAgICAgICAgIGNsYXNzX21hcmtlciA9IDEpICU+JSAKICBzcHJlYWQoY2xhc3Njb2RlLGNsYXNzX21hcmtlciwgZmlsbCA9IDApICU+JSAKICAgIG11dGF0ZShzaXRlID0gcGFzdGUoJ3NpdGUnLHNpdGUsIHNlcCA9ICdfJyksCiAgICAgICAgIHNpdGVfbWFya2VyID0gMSkgJT4lIAogIHNwcmVhZChzaXRlLHNpdGVfbWFya2VyLCBmaWxsID0gMCkgJT4lIAogIHNlbGVjdChsb2dfZGVuc2l0eSwgY29udGFpbnMoJ3llYXJfJyksIGNvbnRhaW5zKCdkaWRfJyksCiAgICAgICAgIGNvbnRhaW5zKCdjbGFzc2NvZGVfJyksIGNvbnRhaW5zKCdzaXRlXycpKSAlPiUgCiAgbXV0YXRlKGNvbnN0YW50ID0gMSkKCmxldmVsc190b19kcm9wIDwtIGMobWluKHBvc19yZWdfZGF0YSR5ZWFyKSxzb3J0KHVuaXF1ZShwb3NfcmVnX2RhdGEkY2xhc3Njb2RlKSlbMV0sCiAgICAgICAgICAgICAgICAgICAgc29ydCh1bmlxdWUocG9zX3JlZ19kYXRhJHNpdGUpKVsxXSkKCnN0YW5fcmVnX2RhdGEgPC0gc3Rhbl9yZWdfZGF0YSAlPiUgCiAgc2VsZWN0KC15ZWFyXzIwMDAsIC1kaWRfMjAwMywgLXNpdGVfQU5BQ0FQQV9BRE1JUkFMUywgLWNsYXNzY29kZV9hY29yKQogICAgICAgICAgICAgICAgICAgIAoKeSA8LSBhcy5udW1lcmljKHN0YW5fcmVnX2RhdGEkbG9nX2RlbnNpdHkpCgp4IDwtIHN0YW5fcmVnX2RhdGEgJT4lIAogIHNlbGVjdCgtbG9nX2RlbnNpdHkpICU+JSAKICBhcy5tYXRyaXgoKQoKCnN0YW5fZml0IDwtIHN0YW4oCiAgZmlsZSA9ICcuLi9zY3JpcHRzL2Fobm9sZF9yZWcuc3RhbicsCiAgZGF0YSA9IGxpc3QoCiAgICBudW1fcGFycyA9IGRpbSh4KVsyXSwKICAgIG51bV9vYnMgPSBsZW5ndGgoeSksCiAgICB5ID0geSwKICAgIHggPSB4CiAgKSwKICBjaGFpbnMgPSA0LCAKICB3YXJtdXAgPSAxMDAwLAogIGl0ZXIgPSAyMDAwLAogIGNvcmVzID0gNCwgCiAgcmVmcmVzaCA9IDEwMAopCgpkaWRfdGVybXMgPC0gd2hpY2goc3RyX2RldGVjdChjb2xuYW1lcyh4KSwnZGlkJykpCgpkaWRfcGxvdCA8LSBzdGFuX2ZpdCAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICBzZWxlY3RfKC5kb3RzID0gYXMubGlzdChkaWRfdGVybXMpKSAlPiUgCiAgZ2F0aGVyKGRpZCxlZmZlY3QpICU+JSAKICAjIG11dGF0ZSh5ZWFyID0gc3RyX3JlcGxhY2UoZGlkLCdkaWRfJywnJykgJT4lIGFzLm51bWVyaWMoKSkgJT4lIAogIGdyb3VwX2J5KGRpZCkgJT4lIAogIHN1bW1hcmlzZShtZWFuX2VmZmVjdCA9IG1lYW4oZWZmZWN0KSwKICAgICAgICAgICAgdG9wID0gc29ydChlZmZlY3QpW3JvdW5kKC45NzUgKiBsZW5ndGgoZWZmZWN0KSldLAogICAgICAgICAgICBib3R0b20gPSBzb3J0KGVmZmVjdClbcm91bmQoLjAyNSAqIGxlbmd0aChlZmZlY3QpKV0pICU+JSAKICBnZ3Bsb3QoKSArIAogIGdlb21faGxpbmUoYWVzKHlpbnRlcmNlcHQgPSAwKSkgKyAKICAjIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAyMDAzKSwgY29sb3IgPSAncmVkJywgbGluZXR5cGUgPSAyKSArCiAgZ2VvbV9wb2ludHJhbmdlKGFlcygxOmxlbmd0aChtZWFuX2VmZmVjdCksbWVhbl9lZmZlY3QsIHltYXggPSB0b3AsIHltaW4gPSBib3R0b20pKSArIAogIHlsYWIoJ0VzdGltYXRlZCBNTFBBIEVmZmVjdCcpICsgCiAgIyBnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoZGF0YSA9IGRhdGFfZnJhbWUoeCA9IDIwMDMsIHkgPSAxKSwgYWVzKHgseSwgbGFiZWwgPSAnTUxQQSBFbmFjdGVkJyksbnVkZ2VfeCA9IDIpICsgCiAgeGxhYignWWVhcicpCgoKYGBgCgpPSyEgVGhpbmdzIHdvcmsuIE1vdmluZyBvdmVyIHRvIGBydW5fYWhub2xkYCBmb3IgZm9ybWFsIGNvbnN0cnVjdGlvbiBvZiB0aGlzIHByb2Nlc3MKCiMjIyBNdWx0aS1sZXZlbCAoaGllcmFyY2hpY2hhbCkgbm90ZXMKCk9LLCBzbyBJIHRoaW5rIEknbSBmaW5hbGx5IHN0YXJ0aW5nIHRvIGdldCB0aGUgaGFuZyBvZiB0aGlzLiBUaGUgY29uZnVzaW9uLCBmcm9tIGEgcmVncmVzc2lvbiBwb2ludCBvZiB2aWV3LCBpcyBob3cgbWVjaGFuaWNhbCBkbyB5b3UgaGF2ZSB0byBiZSBhYm91dCB0aGUgIm11bHRpbGV2ZWwgcGFydCIuIAoKTG9vayBhdCBHZWxtYW4gMTIuMTUgYW5kIHRoZSBjb2RlIHRoZXJlLiAKCllvdXIgY29uZnVzaW9uIGhhcyBiZWVuLCBzYXkgeW91J3ZlIGdvdCBvYnNlcnZhdGlvbnMgYXQgdGhlIHRyYW5zZWN0IGxldmVsLCBhbmQgeW91IHdhbnQgdG8gaW5jbHVkZSBzcGVjaWVzIGxldmVsIGNvdmFyaWF0ZXMuIEluIGEgZml4ZWQgZWZmZWN0cyB3b3JsZCB0aGlzIHdvdWxkbid0IHdvcms6IHlvdSBjYW4ndCBlc3RpYW10ZXMgc3BlY2llcyBsZXZlbCBmaXhlZCBlZmZlY3RzLCBhbG9uZyB3aXRoIHRoaW5ncyBsaWtlIHZiay4gdGhhdCBkb24ndCB2YXJ5IHdpdGhpbiBhIHNwZWNpZXMuIFlvdSBjYW4gZWl0aGVyIGluY2x1ZGUgc3BlY2llcyBmaXhlZCBlZmZlY3RzLCBvciBjb21wb25lbnQgdGhpbmdzIHRoYXQgZGVmaW5lIHNwZWNpZXMuIAoKVGhlIHdheSBHZWxtYW4gdGFsa3MgYWJvdXQgdGhpcyBpbiBtdWx0aWxldmVsIG1vZGVsaW5nLCBpcyB0aGF0IHlvdSBjYW4gaW5zdGVhZCBtb2RlbCB0aGlzIGluIGEgaGllcmFyY2hpY2FsIG1hbm5lciwgd2hlcmUgdGhlIGNvZWZmaWNpZW50cyBvZiB0aGUgc3BlY2llcyBmaXhlZCBlZmZlY3RzIGFyZSBhIGZ1bmN0aW9uIG9mIHRoaW5ncyBsaWtlIHZiay4gVGhpcyBtYWtlcyBzZW5zZSwgYnV0IHRoZSBxdWVzdGlvbiBpcyB0aGUgbWVjaGFuaWNzIG9mIHRoaXMuIE15IGltcHJlc3Npb24gd2FzIHRoYXQgSSB3b3VsZCBoYXZlIHRvIGRvIHRoaXMgYWxsIG1hbnVhbGx5LCBpLmUuIHRha2UgdGhlIGJldGFzIG9mIHRoZSBmaXhlZCBlZmZlY3RzLCB0aGVuIHdyaXRlIHVwIGEgcmVncmVzc2lvbiBvZiB0aG9zZSBiZXRhcyBhcyBhIGZ1bmN0aW9uIG9mIHZiayBldGMuIE1ha2VzIHNlbnNlIGJ1dCBhIHRvdGFsIHBhaW4gaW4gdGhlIGFzcy4gCgpMb29raW5nIGF0IEdlbG1hbiBwYWdlIDI2NiB0aG91Z2gsIGl0IGJlY29tZXMgY2xlYXJlci4gSXQgc2VlbXMgbGlrZSBtZWNoYW5pY2FsbHkgeW91IGNhbiBkbyB0aGlzIGp1c3QgYnkgY29udmVydGluZyB0aGUgZml4ZWQgZWZmZWN0cyB0byBjbHVzdGVyZWQgcmFuZG9tIGVmZmVjdHMsIGFuZCB0aGVuIGluY2x1ZGluZyB2YmsgYXMganVzdCBhbm90aGVyIGNvZWZmaWNpZW50LiAKCmUuZy4gYGxtZXIoeSB+IHggKyB2YmsgKyAoMSB8IHNwZWNpZXMpKWAKCgojIyBQcm9wZW5zaXR5IFNjb3JlcwoKYGBge3J9CgpgYGAKCkFkZCBpbiBicm9hZCBiaW9yZWdpb24gZWZmZWN0CgpUaGF0IGNvdWxkIGp1c3QgYmUgcmVjb3ZlcnkgaW5zaWRlIGFuZCBub3Qgc3BpbGxvdmVyLiBEbyB5b3UgaGF2ZSB0byBoYXZlIHNwaWxsb3ZlcgoKVGhleSBkb24ndCBjb3VudCB0aGUgCgpMb29rIGF0IFN0ZXZlJ3MgQkFDSSByZXNwb25zZSB0byBSYXkncyAKCldoYXQgaGFwcGVucyB0byB0aGUgcmVndWxhaW9ucyBvdXRzaWRlIGluIGFkZGl0aW9uIHRvIHRoZSByZXNlcnZlLiBBIHNpbXBsZSBtb2RlbCB0aGF0IGxvb2tzIGF0IHdoYXQgd291bGQgeW91IGV4cGVjdCAKCkdvb2QgZGF0YSBmb3IgdGhlIG1haW5sYW5kIAoKTG9vayBpbnRvIGxpdGVyYXR1cmUgZm9yIHByaW9ycyAKCkknbSBnb2luZyB0byBzaG93IHRoYXQgeW91IGNhbiBkaXNlbnRhbmdsZSByZWNydWl0bWVudCBmcm9tIGxlbmdodHMKCiMjIDIwMTctMDMtMTUKCiMjIyBFeHByZXNzaW5nIE1MUEEgZWZmZWN0CgpNaWdodCBiZSBhIGdvb2QgaWRlYSB0byBzaG93IHRoZSBzaWduaWZpY2FuY2Ugc3RhdGlzdGljYWxseSwgYnV0IHRoZSBlZmZlY3QgdGhyb3VnaCBzaW11bGF0aW9uLiBTaW11bGF0ZSBkcmF3cyBmcm9tIHRoZSBqb2ludCBwb3N0ZXJpb3Igd2l0aCBhbmQgd2l0aG91dCBNTFBBLCBzaG93IG1lYW4gZGVuc2l0aWVzLiBFYXNpZXIgdG8gdW5kZXJzdGFuZCwgYWxsb3dzIHlvdSB0byBjb21iaW5lIHRoZSBuZXQgZWZmZWN0IG9mIGh1cmRsZSBjb21wb25lbnQKCiMjIDIwMTctMDMtMTYKCiMjIyBDaGVjayBpbiB3aXRoIEplbgoKKiBDaGVjayBpbiB3aXRoIHRoZSBpZGVhIG9mIG1vcmUgbG9jYWwgaW5kaWNpZXMgb2YgRU5TTy9QRE8KCiogTm8gYmlnIEVOU08gZXZlbnQgdGlsbCAyMDEzCgoqIE1pZ2h0IG5lZWQgdG8gZXhwbG9yZSByZW1vdmluZyBwYWludGVkIGdyZWVubGluZyBzaW5jZSB0aGV5IGFyZSBib3R0b20gZHdlbGxpbmcgY3J5cHRpYy1pc2guIFRlbmQgdG8gYmUgY291bnRlZCBtb3JlIGZyZXF1ZW50bHkgd2hlbiB0aGVyZSB3YXNuJ3QgbXVjaCBlbHNlLiAKCiogRHJvcCBzYW50YSBiYXJiYXJhIGlzbGFuZCBlbnRpcmVseSAob25lIG9mZiBzYW1wbGUsIDQgeWVhcnMpCgoqIExldCdzIHRoaW5rIGFib3V0IHBhcnNpbmcgdGhpcyBieSBzcGVjaWVzLiBGaXNoaW5nIGlzIHZlcnkgZGlmZmVyZW50IGFjcm9zcyBkaWZmZXJlbnQgc3BlY2llcyBpbiBoZXJlLCB3aGF0IHNwZWNpZXMgYXJlIHJlYWxseSBkcml2aW5nIHRoZSBhbmFseXNpcz8gQXJlIGRpZmZlcmVudCBzcGVjaWVzIGRpc3Byb3BvcnRpb25hdGVseSBkcml2aW5nIHRoZSByZXN1bHRzIAoKKiBXZSBoYXZlIGJlZm9yZSBhbmQgYWZ0ZXIgZGF0YSBmcm9tIHRoZSBvdmVyZmxpZ2h0cywgc28gY291bGQgYXQgbGVhc3QgdXNlIHRoYXQgYXMgYSBwcmlvciBvbiB0aGUgc2NhbGUgb2YgcmVkaXN0cmlidXRpb24uIFNBTVNBUCBtaWdodCBiZSBhYmxlIHRvIHBpY2sgdXAgdGhlIHBvdGVudGlhbCAiYmx1ZSBwYXJhZG94IiBzaWRlIG9mIHRoaW5ncywgYXMKCiogV2hhdCBpZiB0aGlzIGlzIGFsbCBqdXN0IGEgcmVjcnVpdG1lbnQgc2lnbmFsIAoKKiBXZSBjb3VsZCBsb29rIGF0IHRoZSBTTVVSRiBkYXRhIHRvIGdldCBhbiBpZGVhIG9mIHRoZSByZWNydWl0bWVudCB0cmVuZHMgCgoqIFNvbWV0aGluZyB3ZWlyZCBoYXBwZW5lZCBpbiAyMDA4LTIwMTAgYWNyb3NzIGFsbCB0aGUgQ0kgZGF0YQoKKiBQSVNDTyBhc3N1bWVzIHRoYXQgYWxsIHNwZWNpZXMgaGF2ZSB0aGUgc2FtZSBwcm9iYWJpbGl0eSBvZiBiZWluZyBzZWVuIGFueXdoZXJlIGluIGFsbCB0aGUgaXNsYW5kcy4gTWlnaHQgYmUgd29ydGggbG9va2luZyBpbnRvIHdoYXQgaGFwcGVucyBpZiB5b3UgemVybyBmaWxsIGJ5IGRhdGEtYmFzZSB3aWRlIAoKIyMgMjAxNy0yMS0wMwoKVGhpbmdzIGFyZSBsb29raW5nIHByZXR0eSBzdHJvbmcuIEJhc2ljIE1vZGVsIGRpYWdub3N0aWNzIGxvb2sgc29saWQgZm9yIHRoZSBtb3N0IHBhcnQsIHRob3VnaCB0aGUgTE1FUiBhcHByb2FjaCBpcyBhIGJpdCBza2V3ZWQgdG8gdGhlIHJpZ2h0LiBCdXQgbm8gYWxhcm0gYmVsbHMuIFRoZSBiaWdnZXN0IGlzc3VlIGlzIHJlYWxseSBsb3cgZWZmZWN0aXZlIHNhbXBsZXMgc2l6ZXMgZm9yIHNldmVyYWwgc3BlY2llcywgYXMgd2VsbCBhcyBjb2xsaW5lYXJpdHkgYmV0d2VlbiBhIGZldyBvZiB0aGUgbW9kZWwgcGFyYW1ldGVycyAobG9hZCB1cCB0aGUgU1RBTiBydW4gYW5kIGxhdW5jaCBzaGlueXN0YW4gdG8gZGlnIGludG8gdGhpcyBhIGJpdCkuIAoKQSBmZXcgdGhpbmdzIHlvdSBjYW4gZG8gdG8gdHJ5IGFuZCBkZWFsIHdpdGggdGhhdC4gUmUtcnVuIHRoZSBtb2RlbCB3aXRoIG9ubHkgbGV0J3Mgc2F5IHRoZSB0b3AgNzUlIHBlcmNlbnRpbGUgYnkgcG9zaXRpdmUgb2NjdXJhbmNlIHNwZWNpZXMsIHRvIG1ha2Ugc3VyZSB0aGF0IHlvdSdyZSBub3QgZ2V0dGluZyB0b28gdGhyb3duIGJ5IGEgYnVuY2ggb2YgcmVhbGx5IHJhcmUgc3BlY2llcy4gQ2FuIGFsc28gdHJ5IHJlcnVubmluZyB3aXRob3V0IHBhaW50ZWQgZ3JlZW5saW5nLCBzaW5jZSBKZW4gc2VlbXMgdG8gdGhpbmsgdGhvc2UgYnVnZ2VycyBtaWdodCBiZSBhIHByb2JsZW0uIEknbSBhIGxpdHRsZSBoZXNpdGFudCB0byBkbyB0b28gbXVjaCBqdWRnZW1lbnQgYmFzZWQgcHJ1bmluZyBvZiB0aGUgZGF0YS4gS2V5IHRoaW5ncyBpcyBkb2VzIGl0IHJlYWxseSBjYXVzZSB0aGUgcmVzdWx0cyB0byBicmVhayBkb3duLiAKCkplbiBhbHNvIHJhaXNlZCB0aGUgaXNzdWUgb2YgdGhlIHplcm8gZmlsbGluZy4gWW91IGRpZCB5b3VyIHplcm8gZmlsbGluZyBieSBzaXRlLiBJdCBzZWVtcyB0aGF0IHdoZW4gSmVuIHdhcyBnb2luZyBmcm9tIHJhdyBsZW5ndGhzIHRvIGRlbnNpdGllcywgc2hlIHdhcyB6ZXJvIGZpbGxpbmcgYnkgcmVnaW9uLiBTbywgYSBnYXJpYmFsaWRpIHNob3VsZCBiZSBtaXNzaW5nIGZyb20gZXZlcnkgdHJhbnNlY3QgaW4gU2FuIE1pZ3VlbC4gVGhpcyBzZWVtcyBhIGxpdGxlIGV4dHJlbWUgdG8gbWUsIGJ1dCB5b3UgY2FuIHBsYXkgd2l0aCB0aGlzIG9uY2UgeW91IGdldCB0aGUgYWJpbGl0eSB0byBtb3ZlIGZyb20gbGVuZ2h0cyB0byBkZW5zaXRpZXMuIEkgcmVhbGx5IHdhbnQgdG8gaG9uZSBpbiBvbiBhbnkgc3ViamVjdGl2ZSBkZWNpc2lvbnMgdGhhdCBtaWdodCBiZSBkcml2aW5nIHRoZSByZXN1bHRzLCBhbmQgdGhpcyBzZWVtcyBsaWtlIGEgcG90ZW50aWFsbHkgYmlnIGNhbmRpZGF0ZQouIAoKVXBkYXRlOiByZW1vdmluZyBwYWludGVkIGdyZWVubGluZyBoYXMgbm8gcmVhbCBlZmZlY3Qgb24gcmVzdWx0cy4gUGhldy4gCgpSdW5uaW5nIG5vdyB3aXRoIG9ubHkgdGhlIHRvcCA1MHRoIHBlcmNlbnRpbGUgb2Ygc3BlY2llcyBpbmNvcnBvcmF0ZWQgaW4gdGhlIGFuYWx5c2lzLCBzZWVpbmcgd2hhdCB0aGF0IGRvZXMuIAoKT25lIHRob3VnaHQgb24gdGhlIHJhbmRvbSB2cy4gZml4ZWQgZWZmZWN0cyB0aGluZzogc2hvdWxkIHNwZWNpZXMgcmVhbGx5IGJlIGEgcmFuZG9tIGVmZmVjdD8gTWF5YmUgeW91IHNob3VsZCBvbmx5IGhhdmUgdmFyeWluZyBzbG9wZXMgYnV0IG5vdCBpbnRlcmNlcHRzIGJ5IHNwZWNpZXMsIHNvIGhhdmUgZml4ZWQgZWZmZWN0cyBieSBzcGVjaWVzIGNhdGVnb3J5LCBhbmQgdGhlbiB0ZW1wZXJhdHVyZSBhbmQgcmVnaW9uIGVmZmVjdHMgYnkgc3BlY2llcy4KCldvb29vbyBzcGVjaWVzIGVmZmVjdHMgZG9uJ3QgbWF0dGVyIGVpdGhlcgoKWW91IHNob3VsZCBnbyB0aHJvdWdoIGFuZCBzcGVsbCBvdXQgd2h5IHlvdSB0aGluayBzb21lIHRoaW5ncyBhcmUgcmFuZG9tIGFuZCBzb21lIGFyZSBmaXhlZCBlZmZlY3RzLCBkcmF3aW5nIGZyb20gdGhlIGdlbG1hbiBmcmFtZXdvcmssIHdoZXJlIHRoZSBuYXR1cmUgb2YgdGhlIGhpZXJhcmNoaWNoYWwgcHJpb3IgaXMgcmVhbGx5IHRoZSBkZWZpbmluZyBjaGFyYWN0ZXJpc3RpYyAKCiMjIFNrZXRjaGluZyBvdXQgSHlwb3RoZXNpcyBSdW5zCgpXaGF0IGFyZSB0aGUgaHlwb3RoZXRpY2FsIHN0YXRlcyBvZiB0aGUgTVBBIHdvcmxkIHRoYXQgeW91IHdhbnQgdG8gcnVuIG92ZXI/IE9uZSBvcHRpb24gaXMgdG8gc3BlY2lmeSBhIGhhbmRmdWwgb2YgYm91dGlxdWUgbW9kZWwgcnVuczogbW9kZWwgMSwgMiwgMyBldGMsIGVhY2ggZGVzaWduZWQgdG8gZXZhbHVhdGUgYSB2ZXJ5IHNwZWNpZmljIHNldCBvZiBjaXJjdW1zdGFuY2VzLiBUaGUgb3RoZXIgaXMgdG8gc3BlY2lmeSBhIHNldCBvZiBrZXkgbGV2ZWxzLCBhbmQgdGhlbiBtb250ZSBjYXJsbyBvdmVyIGNvbWJpbmF0aW9ucyBvZiB0aG9zZSBsZXZlcnMuIAoKUmVnYXJkbGVzcywgdGhlIGtleSB0aGluZ3Mgc2VlbSB0byBiZQoKICAxLiBTdHJlbmd0aCBvZiBkZW5zaXR5IGRlcGVuZGVuY2UKICAyLiBOYXR1cmUgb2YgZGVuc2l0eSBkZXBlbmRlbmNlCiAgMy4gaW5pdGlhbCBiIGFuZCBmCiAgNC4gTGFydmFsIG1vdmVtZW50CiAgNS4gQWR1bHQgbW92ZW1lbnQKICA2LiBBZ2UgYXQgbWF0dXJpdHkgCiAgNy4gRmxlZXQgcmVhY3Rpb24KICA4LiBTcGVjaWVzIGNvbXBvc2l0aW9uCiAgOS4gU2NhbGUgb2YgTVBBIHJlbGF0aXZlIHRvIG1vdmVtZW50CiAgClRoZSBmaXJzdCA2IGFyZSByZWxhdGl2ZWx5IHN0cmFpZ2h0Zm9yd2FyZC4gU2VlbXMgcG9zc2libHkgZWFzaWVyIHRvIG1vbnRlIGNhcmxvIGFuZCB0aGVuIHB1bGwgb3V0IGNhc2Ugc3R1ZHkgc2NlbmFyaW9zIHRoYXQgeW91IGFyZSBpbnRlcmVzdGVkIGluLCBzaW5jZSBzcGVlZCByZWFsbHkgaXNuJ3QgdGhlIGlzc3VlIGhlcmUuIAoKWW91IGNvdWxkIGFsc28gdXNlIHRoYXQgdG8gZWFzaWx5IGNyZWF0ZSBlbnNlbWJsZXMgb2Ygc3BlY2llcy4gCgpTbywgZm9yIGEgZ2l2ZW4gInJ1biIgeW91J2Qgc3BlY2lmeSBob3cgbWFueSBzcGVjaWVzIHlvdSB3YW50IHRvIGdlbmVyYXRlLCBhbmQgdGhlbiBwcm9qZWN0IHRoZW0gYW5kIGFnZ3JlZ2F0ZS4gU28sIHlvdSBjb3VsZCBzcGVjaWZ5IG9uZSBzcGVjaWVzIGlmIHlvdSB3YW50IG90IG1ha2UgaXQgY2xlYXIsIG9yIGFuIGFzc2VtYmxhZ2Ugb2YgbWFueSBkaWZmZXJlbnQgc3BlY2llcy4gCgpUaGUgcmlzayB3aXRoIHRoaXMgYXBwcm9hY2ggaXMgdGhhdCB5b3UgbWlnaHQganVzdCBnZXQgYSBnaWdhbnRpYyBtZXNzIG9mIHJlc3VsdHMuIEJ1dCwgeW91IGNhbiBlYXNpbHkgcGFyZSB0aGlzIGFwcHJvYWNoIGRvd24gdG8gYSBjb25jcmV0ZSBzZXQgaWYgeW91IHdhbnQuIEkgdGhpbmsgdGhpcyBnZXRzIGF3YXkgZnJvbSAiY2hlcnJ5IHBpY2tpbmciIHNjZW5hcmlvcyB0aGF0IGZpdCB5b3VyIHN0b3J5LiBZb3UgY2FuIHByZXNlbnQgYSBnaWFudCBhcnJheSBpbiB0cmVsbGlzY29wZSBvZiBvdXRjb21lcywgYW5kIHRoZW4gY2hvb3NlIHNvbWUgdG8gcHJlc2VudCBpbiB0aGUgcGFwZXIuIAoKCiAgCiAgMS4gU3RyZW5ndGggb2YgZGVuc2l0eSBkZXBlbmRlbmNlCiAgICAqIHRoaXMgaXMganVzdCBzdGVlcG5lc3MKICAyLiBOYXR1cmUgb2YgZGVuc2l0eSBkZXBlbmRlbmNlCiAgICAqIFlvdSBjYW4gdXNlIHRoZSBiYWJjb2NrIGRlZmluaXRpb25zIHRoYXQgYXJlIGFscmVhZHkgaW4gdGhlcmUKICAzLiBmCiAgICAqIE9uZSBvcHRpb24gaXMganVzdCB0byBzYXkgcGljayBhIHJhbmRvbSBGCiAgICAqIFRoZSBvdGhlciBvcHRpb24gaXMgc29tZSBraW5kIG9mIGVmZm9ydCBkeW5hbWljcyBtb2RlbCwgZnJvbSBvcGVuIGFjY2VzcyB0byBvbmUgd2F5IHRyaXAgZXRjLgogICAgKiBTZWVtcyBleGNlc3NpdmUsIHRoZSBrZXkgdGhpbmcgaXMgaXQgb3ZlcmZpc2hlZCBvciBub3QsIGFuZCBpcyBpdCBnZXR0aW5nIHdvcnNlIG9yIG5vdAogICAgKiBQaWNrIGEgcmFuZG9tIGYsIHJ1biBpdCBvdXQKICAgICogU3RvcCB0aGUgdGhpbmcgYXQgc29tZSByYW5kb20gcG9pbnQuLi4uIHByb2JsZW0gdGhlcmUgaXMgeW91IGNhbid0IGJlIGluICJyZWNvdmVyeSIKICA0LiBMYXJ2YWwgbW92ZW1lbnQKICAgICogaGFyZGVyLiBXaWxsIHRha2Ugc29tZSB0aG91Z2h0IHRvIGRvIHRoaXMgb25lIHJpZ2h0IHJlYWxseS4gS2V5IHRoaW5nIGlzIGRvIHlvdSB3YW50IHRvIGRlYWwgd2l0aCBsYXJ2YWUgb3Igd2l0aCByZWNydWl0cyByZWFsbHkuIFNlZSBob3cgeW91IGRvIGl0IGluIEdBU1AgIAogIDUuIEFkdWx0IG1vdmVtZW50CiAgICAqIEVhc3kgZW5vdWdoLCB3aGF0IHByb3BvcnRpb24gb2YgYWR1bHRzIG1vdmUgZnJvbSBlYWNoIGNlbGwKICA2LiBBZ2UgYXQgbWF0dXJpdHkgCiAgICAqIHNpbXBsZSBlbm91Z2gKICA3LiBGbGVldCByZWFjdGlvbgogICAgKiBEaWx1dGUKICAgICogQ29uY2VudHJhdGUKICA4LiBTcGVjaWVzIGNvbXBvc2l0aW9uCiAgOS4gU2NhbGUgb2YgTVBBIHJlbGF0aXZlIHRvIG1vdmVtZW50CiAgICAqIE1ha2UgdGhlIE1QQXMgYWJvdXQgdGhlIHBhdHRlcm4gb2YgQ0kKCkZvciBub3csIGxldCdzIHRha2UgdGhlIGxpZmUgaGlzdG9yeSBzdHJhaWdodCBvdXQgb2YgdGhlIGRhdGEgdGhhdCBhcmUgYWN0dWFsbHkgdXNlZC4gU28sIGdyYWIgdGhlIHNwZWNpZXMgdGhhdCBtYWtlIGl0IHRocm91Z2ggdGhlIGZpbHRlciBhbmQgcHJvamVjdCB0aG9zZS4gU28sIGVhY2ggcnVuIHdpbGwgdGFrZSB0aGUgbGlmZSBoaXN0b3J5IGRhdGEgYW5kIHJ1biB3aXRoIGl0IHdpdGggYSByYW5kb20gYXNzb3J0bWVudCBvZiB0cmFpdHMuIAoKTGV0J3MgZm9jdXMgb24ga2VlcGluZyBpdCBzaW1wbGUgc3R1cGlkLiBUYWtlIHRoZSBzcGVjaWVzLCBwcm9qZWN0IGZvcndhcmQgd2l0aCBhIHJhbmRvbSBGIGFuZCBhIHJhbmRvbSBzdG9wIHBvaW50LCBhIHN0ZWVwbmVzcyBkcmF3biBmcm9tIHRoZSBmYW1pbHkgZGlzdHJpYnV0aW9uIGZvciB0aGF0IHNwZWNpZXMsIGEgcmFuZG9tIGRlbnNpdHkgZGVuZXBlbmNlIGZvcm0uLi4gbGV0J3Mgc3BlbGwgaXQgb3V0CgoKMS4gRHJhdyBhIHNwZWNpZXMgZnJvbSB0aGUgZGF0YWJhc2UKMi4gRmlsbCBpbiBtaXNzaW5nIG5vbi12YXJpYWxlIGxpZmUgaGlzdG9yeSBjaGFyYWN0ZXJpc3RpY3MgKGUuZy4gbGluZikKMy4gUmFuZG9tbHkgYXNzaWduIGNoYXJhY3RlcmlzdGljcyBvZiBpbnRlcmVzdCAoZGVuc2l0eSBkZXBlbmRlbmNlIGZvcm0sIG1vdmVtZW50LCBldGMuKQo0LiBDcmVhdGUgY29tcGxldGVkIGZpc2ggb2JqZWN0CjUuIENyZWF0ZSBhIGZsZWV0IG9iamVjdAo2LiBGaWxsIGluIHRoZSBmbGVldCBvYmplY3Qgd2l0aCB0aGluZ3MgbGlrZSBGLCBvciBmbGVldCBtb2RlbCBkeW5hbWljcyBldGMuIAo3LiBQYXNzIGEgY29tcGxldGVkIGZpc2ggYW5kIGZsZWV0IG9iamVjdCB0byBgc2ltX2Zpc2hlcnlgCjguIFN0b3JlIHJlc3VsdHMKOS4gUmVwZWF0IHJ1bnMgYSB3aG9sZSBidW5jaCBvZiB0aW1lcy4gCjEwLiBBZ2dyZWdhdGUgYXMgZGVzaXJlZAoKIyA0LzEzLzE3CgpBcyBsb25nIGFzIHRoZSBlcnJvcnMgaW4geW91ciBkZXBlbmRlbnQgdmFyaWFibGUgYXJlIG1lYW4gMCwgdGhlbiB0aGVyZSdzIG5vIHByb2JsZW0uIElmIHRoZXkgYXJlIG5vdCwgb3IgaWYgdGhlIGVycm9ycyBhcmUgYSBmdW5jdGlvbiBvZiB5b3VyIGRlcGVuZGVudCB2YXJpYWJsZSwgdGhlbiB5b3UgZG8gaGF2ZSAgcHJvYmxlbQoKTG9vayBpbiB0byBzdHJhdGlmaWNhdGlvbiBmcm9tIHRoYXQgYm9vayBvZiBLeWxlcwoKCgojIyBDaGVjayBpbiB3aXRoIENPZHkKCk1ha2UgbW9ydGFsaXR5L2dyb3d0aCByYXRlcyBhIGZ1bmN0aW9uIG9mIGJpb21hc3MKCkNoZWNrIG9uIGxpdCBvbiB0aGlzIAoKTWFrZSBwbG90IG9mIGxlbmd0aCBvbiB4IGFuZCB5ZWFyIG9uIHksIHNvIHlvdSBnZXQgYSBidW5jaCBvZiBzdGFja2VkIHNoaWZ0cyBpbiBjb2hvcnRzCgpNYXliZSBhZGQgaW4gYSByaWNrZXIgZnVuY3Rpb24sIHRob3VnaCBtaWdodCBuZWVkIHRvIGRvdWJsZSBjaGVjayBvbiB0aGUgc3RlZXBuZXNzIHZhbHVlcy4gWW91IG1pZ2h0IGJlIG1vdmluZyB0aGluZ3Mgb3ZlciB0aGUgdG8gcmlnaHQgaGFuZCBzaWRlIG9mIAoKIyBFeGFtaW5lIE9TVCBjYXRjaCBkYXRhCgoKYGBge3J9CgoKCm9zdF9yZWdpb25fY2F0Y2ggPC0gcmVhZF9jc3YoJy4uL2RhdGEvU291dGhDb2FzdEh1bWFuQWN0aXZpdGllc0NvbW1lcmNpYWxGaXNoZXJpZXNFY29ub21pY2FuZFNwYXRpYWxEYXRhMTk5MnRvMjAxMi9zY19jb21tX2Zpc2hlcmllc19yZWdpb25fbGFuZGluZ3NfZGF0YV8xOTkyXzIwMTIuY3N2JykgJT4lIAogIHNldF9uYW1lcyhjb2xuYW1lcyguKSAlPiUgdG9sb3dlcigpKQoKb3N0X3JlZ2lvbl9jYXRjaCAlPiUgCiAgbXV0YXRlKHBvdW5kcyA9IHN0cl9yZXBsYWNlKHBvdW5kcywnLCcsJycpICU+JSBhcy5udW1lcmljKCksCiAgICAgICAgIHJldmVudWUgPSBzdHJfcmVwbGFjZV9hbGwocmV2ZW51ZSwiXFwkfCwiLCcnKSwKICAgICAgICAgcHJpY2UgPSBzdHJfcmVwbGFjZShgYXZlcmFnZSBwcmljZWAsJ1xcJCcsJycpKSAlPiUgCiAgZ3JvdXBfYnkoeWVhcixmaXNoZXJ5KSAlPiUgCiAgc3VtbWFyaXNlKGNhdGNoX2xicyA9IHN1bShwb3VuZHMsIG5hLnJtID0gVCkpICU+JSAKICBnZ3Bsb3QoYWVzKHllYXIsY2F0Y2hfbGJzLCBjb2xvciA9IGZpc2hlcnkpKSArIAogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAyMDAzKSwgbGluZXR5cGUgPSAyLCBjb2xvciA9ICdyZWQnKSArCiAgZ2VvbV9saW5lKCkKCmBgYAoKSW50ZXJlc3RpbmcsIHN0YWJsaXNoIHRocm91Z2hvdXQgdGhlIFNDIHJlZ2lvbiwgdGhvdWdoIHRoYXQncyBhIHByZXR0eSBkYW1uIGJpZyBhcmVhCgpgYGB7cn0KCm9zdF9wb3J0X2NhdGNoIDwtIHJlYWRfY3N2KCcuLi9kYXRhL1NvdXRoQ29hc3RIdW1hbkFjdGl2aXRpZXNDb21tZXJjaWFsRmlzaGVyaWVzRWNvbm9taWNhbmRTcGF0aWFsRGF0YTE5OTJ0bzIwMTIvc2NfY29tbV9maXNoZXJpZXNfcG9ydF9sYW5kaW5nc19kYXRhXzE5OTJfMjAxMi5jc3YnKSAlPiUgCiAgc2V0X25hbWVzKGNvbG5hbWVzKC4pICU+JSB0b2xvd2VyKCkpCgpvc3RfcG9ydF9jYXRjaCAlPiUgCiAgZmlsdGVyKHBvcnQgJWluJSBjKCJQb3J0IEh1ZW5lbWUvT3huYXJkIiwgIlNhbnRhIEJhcmJhcmEiLCJWZW50dXJhIikpICU+JSAKICBtdXRhdGUocG91bmRzID0gc3RyX3JlcGxhY2UocG91bmRzLCcsJywnJykgJT4lIGFzLm51bWVyaWMoKSwKICAgICAgICAgcmV2ZW51ZSA9IHN0cl9yZXBsYWNlX2FsbChyZXZlbnVlLCJcXCR8LCIsJycpLAogICAgICAgICBwcmljZSA9IHN0cl9yZXBsYWNlKGBhdmVyYWdlIHByaWNlYCwnXFwkJywnJykpICU+JSAKICBncm91cF9ieSh5ZWFyLGZpc2hlcnkpICU+JSAKICBzdW1tYXJpc2UoY2F0Y2hfbGJzID0gc3VtKHBvdW5kcywgbmEucm0gPSBUKSkgJT4lIAogIGdncGxvdChhZXMoeWVhcixjYXRjaF9sYnMsIGNvbG9yID0gZmlzaGVyeSkpICsgCiAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IDIwMDMpLCBsaW5ldHlwZSA9IDIsIGNvbG9yID0gJ3JlZCcpICsKICBnZW9tX2xpbmUoc2hvdy5sZWdlbmQgPSBGKSArIAogIGZhY2V0X3dyYXAofmZpc2hlcnksIHNjYWxlcyA9ICdmcmVlX3knKSArIAogIHRoZW1lKGF4aXMudGV4dC55ID0gIGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkKCgpgYGAKCgojIDQvMTQvMTcKCkknbSBob25lc3RseSBjbG9zZSB0byBvdXQgb2YgaWRlYXMuIFRoZXNlIGNhdGNoIGRhdCBhcmUgcHJldHR5IHdvcnJpbmcgdG8gYmUgaG9uZXN0LiBJZiB5b3UgYnV5IHRoZXNlIGRhdGEgYXMgYmVpbmcgcmVwcmVzZW50YXRpdmUgb2YgdGhlIGZpc2hlZCBzcGVjaWVzIG91dCBpbiB0aGUgY2hhbm5lbCBpc2xhbmRzLCB0aGVuIHRoaXMgc3VnZ2VzdHMgYSBkZWNyZWFzaW4gZ2NhdGNoIHRyZW5kIGluIG5lYXJzaG9yZSBmaW5maXNoIGNhdGNoZXMsIG5vdCBzdGFibGUgb3IgaW5jcmVhc2luZy4gVGhhdCByZWFsbHkgbWFrZXMgaXQgaGFyZCB0byBleHBsYWluIHRoZSBNUEEgbWVkaWF0ZWQgImRlY3JlYXNlIiBpbiBhYnVuZGFuY2UuIAoKUG9zc2libGUgZXhwbGFuYXRpb25zIHRoYXQgcmVtYWluLiAKCjEuIFNvbWUgZm9ybSBvZiBkZW5zaXR5IGRlcGVuZGVudCBtb3J0YWxpdHkgKG9yIHJpY2tlciBsaWtlIGR5bmFtaWNzKQogICogQ2FuIG1vZGVsIHRoaXMKCjIuIENhdGNoZXMgYXQgdGhlIGlzbGFuZHMgdGhlbXNlbHZlcyBoYXZlIGJlZW4gc3RhYmxlIG9yIGdvbmUgdXAKICAqIENhbiB0cnkgYW5kIGdldCBzb21lIG1vcmUgcmVnaW9uYWwgZGF0YSB0byBjaGVjayBvbiB0aGlzCiAgCjMuIE9jYW0ncyByYXpvcjogVGhlcmUgd2FzIGp1c3QgYSBkcmFtYXRpYyBlbm91Z2ggc2hpZnQgaW4gc2FtcGxpbmcgcmVnaW1lcyB3aGVuIHRoZSBNUEFzIHdlbnQgaW4gcGxhY2UgdGhhdCBwcmUtYW5kLXBvc3QgYXJlIGp1c3Qgbm90IGNvbXBhcmFibGUgaW4gYW55IHdheSBzaGFwZSBvZiBmb3JtCgo0LiBMZXQncyB3cml0ZSB1cCB0aGUgY3VycmVudCByZXN1bHRzIGFuZCBzdGF0ZSBvZiB0aGUgd29ybGQgdGhpcyB3ZWVrZW5kL25leHQgd2VlayBhbmQgc2VuZCB0aGF0IHRvIGNvbW1pdHRlZSBmb3IgY29tbWVudHMKCiMgU2NyYXBpbmcgQ0RGVyBEYXRhCgoKYGBge3J9CgpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsdWJyaWRhdGUpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeSh0YWJ1bGl6ZXIpCmxpYnJhcnkodGFidWxpemVyamFycykKCmEgPSB0YWJ1bGl6ZXI6OmV4dHJhY3RfdGFibGVzKCIuLi9kYXRhL2NkZnctZGF0YS9sYW5kaW5nczAwX3RhYmxlMTIucGRmIikKCnggPC0gYVtbMV1dCgp4IDwtIGFzX3RpYmJsZSh4KQoKcHJvY2Vzc19jZGZ3IDwtIGZ1bmN0aW9uKHgpewogIAogIHggPC0gYXNfdGliYmxlKHgpCiAgCiAgeCA8LSBzbGljZSh4LCAtKDE6MikpCgogICAgbnVtZm9vIDwtIGZ1bmN0aW9uKHopewogICAgCiAgICB6IDwtIHN0cl9yZXBsYWNlX2FsbCh6LCAnXFwufFxcLCcsJycpCiAgICAKICAgIGlmIChhbnkoaXMubmEoYXMubnVtZXJpYyh6KSkgPT0gRikpewogICAgICAKICAgICAgeiA9IGFzLm51bWVyaWMoeikKICAgIH0gZWxzZXsKICAgICAgeiA9IHoKICAgIH0KICAgIAogICAgfQogICAgCiAgICBicm93c2VyKCkKICAgIHggPC0gbWFwX2RmKHgsIH5udW1mb28pCiAgCn0KCiBiID0gIG1hcF9kZigpCgptYXAoYSwgcHJvY2Vzc19jZGZ3KQoKYGBgCgoK